枢轴未排序[快速排序]

时间:2018-07-29 06:44:37

标签: java quicksort

我这里有我的快速排序课程

package week4;

class QuickSort<T extends Comparable<? super T>> {

    public void display(T[] array) {
        int index;
        for (index = 0; index < array.length - 1; index++)
            System.out.print(array[index] + ", ");
        System.out.println(array[index]);
    }

    private void swap(T[] a, int i, int j) {
        T temp = a[i];
        a[i] = a[j];
        a[j] = temp;
        display(a);
    }

    public void order(T[] a, int i, int j) {
        if (a[i].compareTo(a[j]) > 0)
            swap(a, i, j);
    }

    public void sortFirstMiddleLast(T[] a, int first, int mid, int last) {
        order(a, first, mid); // make a[first] <= a[mid]
        order(a, mid, last); // make a[mid] <= a[last]
        order(a, first, mid); // make a[first] <= a[mid]
    }

    public int partition(T[] arr, int first, int last) {
        int mid = (first + last) / 2;
        sortFirstMiddleLast(arr, first, mid, last);

        swap(arr, mid, last - 1);
        int pivotIndex = last - 1;
        T pivot = arr[pivotIndex];

        int indexFromLeft = first + 1;
        int indexFromRight = last - 2;

        boolean done = false;
        while (!done) {
            while (arr[indexFromLeft].compareTo(pivot) < 0)
                indexFromLeft++;

            while (arr[indexFromRight].compareTo(pivot) > 0)
                indexFromRight--;

            if (indexFromLeft < indexFromRight) {
                swap(arr, indexFromLeft, indexFromRight);
                indexFromLeft++;
                indexFromRight--;
            } else
                done = true;
        }

        // place pivot between Smaller and Larger subarrays
        swap(arr, pivotIndex, indexFromLeft);
        pivotIndex = indexFromLeft;

        // Smaller = a[first pivotIndex-1]
        // Pivot = a[pivotIndex]
        // Larger = a[pivotIndex + 1..the last]
        return pivotIndex;
    }
}

public class Project1B {

    public static void main(String args[]) {
        QuickSort<Integer> ob = new QuickSort<Integer>();

        Integer[] arr = { 10, 7, 8, 9, 1, 5 };

        int n = arr.length;

        ob.partition(arr, 0, n - 1);

        System.out.println("sorted array");
        ob.display(arr);
    }
}

我的输出是这个..:

8、7、10、9、1、5

8、7、5、9、1、10

5,7,8,8,9,1,10

5,7,1,9,9,8,10

5,7,1,8,9,10

排序数组

5,7,1,8,9,10

我的问题是枢轴由于某种原因而没有排序,我不确定为什么...我尝试调试并尝试使用google,但是我很难弄清楚它... < / p>

2 个答案:

答案 0 :(得分:1)

这似乎是快速排序算法的某种混淆实现。

首先,我不知道使用sortFirstMiddleLast方法的意义。我们当然不能说调用此方法后,三个数字在数组中的正确位置。例如,如果这三个数字恰好是数组中的三个最大数字,会发生什么?它也不是快速排序算法的一部分。我会摆脱这种方法。

接着,我们在交换元素时必须包括数组的第一个和最后一个元素,以确保它们位于轴的右侧。因此,替换行

        swap(arr, mid, last - 1);
        int pivotIndex = last - 1;
        T pivot = arr[pivotIndex];

        int indexFromLeft = first + 1;
        int indexFromRight = last - 2;

使用

        swap(arr, mid, last);
        int pivotIndex = last;
        T pivot = arr[pivotIndex];

        int indexFromLeft = first;
        int indexFromRight = last - 1;

接下来,我们需要看一下这两个while循环:

            while (arr[indexFromLeft].compareTo(pivot) < 0)
                indexFromLeft++;

            while (arr[indexFromRight].compareTo(pivot) > 0)
                indexFromRight--;

保证第一个循环在要排序的范围内以indexFromLeft结尾,因为在某个点arr[indexFromLeft]将是一个大于或等于枢轴的数字。如果枢轴碰巧是最大数量,则包括枢轴本身,因为将枢轴放在我们正在排序的子数组的末尾。

另一方面,如果arr[indexFromRight]小于(或等于)枢轴,则第二个循环将终止。但是,如果枢轴本身是要排序的范围内的最小数字,则indexFromRight将偏离该范围。实际上,如果支点恰好是整个数组中的最小数,则没有什么可以阻止此循环 从数组的开头掉落并抛出ArrayIndexOutOfBoundsException。

我们可以通过添加防止indexFromRight超出我们要排序范围的条件来避免这种情况:

            while (indexFromRight > first && arr[indexFromRight].compareTo(pivot) > 0)
                indexFromRight--;

最后,您的代码似乎忽略了快速排序算法工作原理的一个关键方面:它是递归的。一旦将透视图放置在正确的位置,您就必须递归地对其两侧的两个子数组进行排序。为此:

  • 声明partition返回void而不是int,然后删除行return pivotIndex;。您对返回值不做任何事情,所以我们最好也不要使用它。

  • partition方法的末尾添加以下几行,以对子数组进行递归排序:

        partition(arr, first, pivotIndex - 1);
        partition(arr, pivotIndex + 1, last);
    
  • 将以下行添加到partition的开头:

    if (first >= last) { return; }
    

    如果first == last,则表示您正在对一个1元素数组或子数组进行排序,并且可以通过不执行任何操作对其进行排序。同样,如果为first > last,则要排序的子数组为空,也可以不进行任何排序。

答案 1 :(得分:-1)

尝试这样做:

public static int [] quickSort (int [] array, int first, int last){
        int pivot = array[last/2];


        while (!isSorted(array)) {
            int left = first;
            int right = last;
            while (true) {
                while (array[left] < pivot && left < last) {
                    left++;
                }
                while (array[right] >= pivot && right > first) {
                    right--;
                }
                if (array[left] > array[right]) {
                    swap(array, left, right);
                    System.out.println(Arrays.toString(array));
                }
                if (left >= right)
                    break;
                if (right - left == 1)
                    break;
            }
        }

    return array;
}

此方法检查数组是否已排序:

private static boolean isSorted(int [] array){
    for (int i = 0; i < array.length; i++){
        if (array[i] > array[i+1])
            return false;
    }
    return true;
}