簡體   English   中英

Java中的快速排序問題

[英]Quicksort issue in Java

我正在嘗試使用遞歸和幾種輔助方法來實現快速排序。 當我運行程序時,我收到一條越界消息,告訴我我已經轉向數組的索引 -1。 任何人都可以提供有關修復我的 quickSort 方法的建議嗎? (這就是問題所在)。 我知道我的其他方法是正確的。

示例 {7,6,5,4,3,2,1}

應該出來是 {1,2,3,4,5,6,7}

public static <T extends Comparable<? super T>> void quickSort(T[] a) {
        quickSort(a,0,a.length - 1);
    }

    public static <T extends Comparable<? super T>> void quickSort(T[] a,int start,int end) { 
        if(start<end) {
            int pivotIndex = partition(a, start, end);
            quickSort(a,start,pivotIndex-1); // sort left partition
            quickSort(a,pivotIndex+1,end); // sort right partition
        }

    }

    public static <T extends Comparable<? super T>> int partition(T[] a, int start, int end) {
        int mid =midpoint(start,end);
        sortFirstMiddleLast(a,start,mid,end);


        swap(a,mid,end-1);
        int pivotIndex = end -1 ;
        T pivotValue = a[pivotIndex];

        int indexFromLeft = start +1 ;
        int indexFromRight = end -2;
        boolean done = false;
        while (!done) {
            while (a[indexFromLeft].compareTo(pivotValue)<0) {
                indexFromLeft++;
                }
            while (a[indexFromRight].compareTo(pivotValue)>0) {
                indexFromRight--;
            }
            if (indexFromLeft < indexFromRight) {
                swap(a,indexFromLeft,indexFromRight);
                indexFromLeft++;
                indexFromRight--;
            }
            else {
                done=true;
            }

        }
            swap(a,pivotIndex,indexFromLeft);
            pivotIndex=indexFromLeft;

        return pivotIndex;
    }

    public static <T extends Comparable<? super T>> void sortFirstMiddleLast(T[] a, int start, int mid, int end) {
        if (a[start].compareTo(a[mid])>0) {
            swap(a,start,mid);
        }
        else if (a[mid].compareTo(a[end])>0) {
            swap(a,mid,end);
        }
        else if (a[start].compareTo(a[end])>0) {
            swap(a,start,end);
        }
        else if(a[start].compareTo(a[mid])>0) {
            swap (a,start,mid);
        }

        }

    private static int midpoint(int first, int last) {
            return first + (last - first) / 2;
        }

private static void swap(Object[] a, int first, int second) {
        Object temp = a[first];
        a[first] = a[second];
        a[second] = temp;
    }

該代碼是 Hoare 分區方案的變體。 假設您不想向內部循環添加范圍檢查,那么樞軸元素需要在左右索引之間的范圍內。 兩個內部循環之后的 if 應該使用左索引 <= 右索引(而不是 <)。

另一個問題是,在典型的 Hoare 分區方案中,pivot 或 elements = pivot 可以在任何地方結束,而 partition 返回的索引可能不是pivot。 索引只是將數組拆分為元素 <= 樞軸和元素 >= 樞軸(同樣,元素 == 樞軸或樞軸本身可以在任何地方結束)。 這意味着調用代碼不能從遞歸調用中排除返回的索引。 同樣對於典型的 Hoare 分區方案,最后一個元素不能用於樞軸,因為這會導致無限遞歸。 Wiki 文章有一個基於 Hoare 的預遞增和預遞減的快速排序示例。

https://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme

Hoare 分區方案的后增量和減量變化的示例 C 代碼,其中分區邏輯合並到快速排序功能中。 對於 Hoare 分區方案的這種特殊變體,任何元素,包括最后一個元素,都可以用作主元,但是選擇第一個或最后一個元素作為主元會導致最壞情況下 O(n^2) 的時間復雜度對於已經排序或反向排序數據,同時選擇如下所示的中間元素會導致已排序或反向排序數據的最佳情況。

void QuickSort(int a[], int lo, int hi)
{
int i, j;
int p, t;
    if(lo >= hi)
        return;
    p = a[lo + (hi-lo)/2];
    i = lo;
    j = hi;
    while (i <= j){
        while (a[i] < p)i++;
        while (a[j] > p)j--;
            if (i > j)
                break;
            t = a[i];
            a[i] = a[j];
            a[j] = t;
            i++;
            j--;
    }
    QuickSort(a, lo, j);
    QuickSort(a, i, hi);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM