java中的Quicksort算法没有正确排序(第一个元素作为数据透视)

时间:2017-09-24 11:42:36

标签: java algorithm quicksort

我正在进行一项我们应该实现quicksort的任务,第一个元素是pivot。我的代码中存在一个小错误,导致列表元素(用于测试)排序不正确。输出应 1 3 7 8 9 10 但最终 1 7 3 8 9 10 (7和3应切换位置)。我怀疑错误可能在第15-26行之间,但我似乎无法找到它,尽管许多人试图修复它。

任何人都可以看到任何错误?

(在第一个while循环中,我尝试过i< = j而不是i< j但这似乎导致无限循环。已经看到其他示例中的工作但不知道为什么在我的情况下,这不起作用)

public static void quickSort(int[] a, int lo, int hi) {
    if (!(hi > lo)) {
        return;
    }
    int pivot = a[lo];
    int i = lo;
    int j = hi + 1;
    int temp;
    i++;
    j--;
    while (i < j) {
        while (a[i] < pivot) {
            i++;
        }
        while (a[j] > pivot) {
            j--;
        }
        if (i <= j) {
            switchPlace(a, i, j);
            i++;
            j--;
        }
    }
    switchPlace(a, lo, j);
    quickSort(a, lo, j - 1);
    quickSort(a, j + 1, hi);
}

public static void switchPlace(int[] a, int x, int y) {
    int temp = a[x];
    a[x] = a[y];
    a[y] = temp;
}

public static void printList(int[] a) {
    String res = "";
    for (int i = 0; i < a.length; i++) {
        res += a[i] + " ";
    }
    System.out.println(res);
}

public static void main(String[] args) {
    int[] a = { 9, 3, 10, 1, 8, 7 };
    quickSort(a, 0, a.length - 1);
    printList(a);
}

感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

我将在这里描述一种调试此类算法的简单方法,包括:

  1. 对代码的较小部分应该产生一些期望;
  2. 验证这些期望是否得到满足。
  3. 第一点涉及详细了解代码尝试做什么,而第二点则意味着使用某些工具进行检查。 &#34;工具&#34;在这个特定的答案中举例说明的是使用print消息,但一般来说它可能是其他东西(例如一个步调试器)。

    qsort算法的主要操作是围绕枢轴交换元素,以便较小的值在之前,较大的值在其之后。 此过程适用于lohi索引之间的各种子序列。

    现在让我们检查每个子序列是否正确完成此操作。 为此,我们可以显示初始子序列以及交换发生后的子序列,以便我们可以手动检查此操作是否正确执行。

    我们可以在交换部分之前使用类似这样的代码:

        System.out.print("before: ");
        for (int k = lo; k <= hi; k++) {
            System.out.print(a[k] + ", ");
        }
        System.out.println();
    

    交换部分后的类似内容:

        System.out.print("after: ");
        for (int k = lo; k <= hi; k++) {
            System.out.print(a[k]);
            if (k == j) {
                System.out.print(" (pivot)");
            }
            System.out.print(", ");
        }
        System.out.println();
        System.out.println();
    

    示例中序列的输出如下所示:

      

    之前:9,3,10,1,8,7,
      之后:8,3,7,1,9(枢轴),10,

         

    之前:8,3,7,1,
      之后:1,3,7,8(支点),

         

    之前:1,3,7,
      之后:1(枢轴),3,7,

         

    之前:3,7,
      之后:7,3(枢轴),

    我们可以看到长度为2的最后一个子序列出现问题。 优点是我们现在只能专注于这种情况并准确理解会发生什么。

    例如,我们甚至可以直接传递给算法int[] a = {3, 7};

    在仔细考虑在这种情况下会发生什么后,我们可以看到问题包括j索引没有跳过大于枢轴的元素,因为while (i < j)在这种情况下立即退出(我们从一开始就有i == j)。有多种解决方案,似乎有效的方法是在相应条件下使用while (i <= j) - 尽管您明确提到它可能会导致无限循环,但实际上似乎并非如此。

    以下是包含此修复程序的代码(以及上述其他print):

    public static void quickSort(int[] a, int lo, int hi) {
        if (!(hi > lo)) {
            return;
        }
        int pivot = a[lo];
        int i = lo;
        int j = hi + 1;
        int temp;
        i++;
        j--;
    
        System.out.print("before: ");
        for (int k = lo; k <= hi; k++) {
            System.out.print(a[k] + ", ");
        }
        System.out.println();
    
        while (i <= j) {
            while (a[i] < pivot) {
                i++;
            }
            while (a[j] > pivot) {
                j--;
            }
            if (i <= j) {
                switchPlace(a, i, j);
                i++;
                j--;
            }
        }
        switchPlace(a, lo, j);
    
        System.out.print("after: ");
        for (int k = lo; k <= hi; k++) {
            System.out.print(a[k]);
            if (k == j) {
                System.out.print(" (pivot)");
            }
            System.out.print(", ");
        }
        System.out.println();
        System.out.println();
    
        quickSort(a, lo, j - 1);
        quickSort(a, j + 1, hi);
    }
    
    public static void switchPlace(int[] a, int x, int y) {
        int temp = a[x];
        a[x] = a[y];
        a[y] = temp;
    }
    
    public static void printList(int[] a) {
        String res = "";
        for (int i = 0; i < a.length; i++) {
            res += a[i] + " ";
        }
        System.out.println(res);
    }
    
    public static void main(String[] args) {
        //int[] a = {3, 7};
        //int[] a = { 9, 3, 10, 1, 8, 7 };
        int[] a = {24, 2 , 45 ,20 ,56 ,75 ,2 ,56 ,99 ,53 ,12};
        quickSort(a, 0, a.length - 1);
        printList(a);
    }
    

答案 1 :(得分:0)

这可以解决您的问题:

public static void quickSort(int[] a, int lo, int hi) {
        if (!(hi > lo)) {
            return;
        }
        int pivot = a[lo];
        int i = lo - 1;
        int j = hi + 1;
        int temp;
        while (i < j) {
            do {
                i++;
            } while (a[i] < pivot);
            do {
                j--;
            } while (a[j] > pivot);
            if (i < j) {
                switchPlace(a, i, j);
                i++;
                j--;
            }
        }
        switchPlace(a, lo, j);
        quickSort(a, lo, j - 1);
        quickSort(a, j + 1, hi);
    }