合并步骤之后的一些更大元素不在枢轴的右侧

时间:2015-05-06 22:58:46

标签: java algorithm quicksort

我编写了快速排序算法,在大多数示例中都给出了正确答案(可能不是全部)。

帖子底部的代码给出了输出:

7 3 5 8 3 1 
pivot: 5
i = 0 j = 5 swaps 7 with 1
1 3 5 8 3 7 
i = 2 j = 4 swaps 5 with 3
1 3 3 8 5 7 //BUT the pivot was 5 why there is 5 on the right from 8?
pivot: 3
i = 1 j = 2 swaps 3 with 3
1 3 3 8 5 7 
pivot: 1
i = 0 j = 0 swaps 1 with 1
1 3 3 8 5 7 
pivot: 3
i = 2 j = 2 swaps 3 with 3
1 3 3 8 5 7 
pivot: 5
i = 3 j = 4 swaps 8 with 5
1 3 3 5 8 7 
pivot: 8
i = 4 j = 5 swaps 8 with 7
1 3 3 5 7 8 //FINALLY CORRECT RESULT

这最终是正确的结果,但在输出的开始出现异常。在第一次合并之后,我们有1 3 3 8 5 7,但是枢轴是5.最后,数组排序正确。我找不到会使算法失败的数组。

我的代码在哪里犯了错误?

public class Quicksort {

    public static void partition(int[] t, int i, int j) {
        if (i >= j) {
            return;
        }
        int start = i, end = j;
        int pivot = t[(i + j) / 2]; // select the pivot as the middle value
        System.out.println("pivot: " + pivot);
        int temp;
        while (i < j) {
            while (t[i] < pivot) { // looking for value greater or equal to the  pivot
                i++;
            }
            while (t[j] > pivot) { // looking for value lower or equal to the  pivot
                j--;
            }
            System.out.println("i = " + i + " j = " + j + " swaps " + t[i] + " with " + t[j]);
            if (i <= j) {
                temp = t[i]; // swap
                t[i] = t[j];
                t[j] = temp;
                i++; // move to the next element
                j--; // move to the prev element
            }
            display(t);
        }
        partition(t, start, j); // partition for the left part of the array
        partition(t, i, end); // partiion for the right part of the array
    }

    public static void display(int[] t) {
        for (int el : t)
            System.out.print(el + " ");
        System.out.println();
    }

    public static void main(String[] args) {
        int[] t = { 7, 3, 5, 8, 3, 1 };
        display(t);
        partition(t, 0, t.length - 1);
    }
}

1 个答案:

答案 0 :(得分:1)

您的排序算法基本上是正确的。

我相信我们可以证明您的分区步骤会导致:

all elements in the left part <= pivot

all elements if the right part >= pivot

然后单独排序就足够了。确认小阵列,并有感应证明。

要获得像[< pivot, = pivot, > pivot]这样的“正确”分区,您需要确保正确维护不变量。

您可能需要三个指针,而不是您正在使用的两个指针。请参阅Dutch National Flag problem

不过,你应该调用你的递归方法sort而不是分区。 while循环是分区步骤。