簡體   English   中英

更改我的quickSort算法Java中的數據透視

[英]change pivot in my quickSort algorithm java

我使用數組中的第一個元素作為樞軸實現了一個有效的quickSort算法,如下所示:

public int[] quickSort( int[] a, int start, int end){

    int l = start;
    int r = end;

    int pivotIndex = start; //<---- first element in the array as pivot! 

    // must be at least two elements
    if ( end - start >= 1){

        // set pivot
        int pivot = a[pivotIndex];


        while ( r > l ){
            // scan from the left
            while ( a[l] <= pivot && l <= end && r > l  ){
                l++;
            }
            while ( a[r] > pivot && r >= start && r >= l){
                r--;
            }
            if ( r > l ){
                this.swap(a, l, r);
            }
        }
        this.swap(a, pivotIndex, r);

        System.out.println("calling quickSort on " + start + " and " + (r-1));                 
        quickSort(a, pivotIndex, r - 1); // quicksort the left partition
        System.out.println("calling quickSort on " + (r+1) + " and " + end);
        quickSort(a, r + 1, end);   // quicksort the right partition

    } else {
        return a;
    }

    return a;
}    

這樣做很好,但是如果我將pivotIndex更改為可以說int pivotIndex = end; 我得到這個結果:

run:
2, 8, 7, 1, 3, 5, 6, 4, 
2, 8, 7, 1, 3, 5, 6, 4, 
swapping l:8 and r:4
2, 4, 7, 1, 3, 5, 6, 8, 
swapping l:7 and r:3
2, 4, 3, 1, 7, 5, 6, 8, 
swapping l:8 and r:1
calling quickSort on 0 and 2
calling quickSort on 4 and 7
2, 4, 3, 8, 7, 5, 6, 1, 
swapping l:7 and r:1
2, 4, 3, 8, 1, 5, 6, 7, 
swapping l:7 and r:1
calling quickSort on 4 and 3
calling quickSort on 5 and 7
2, 4, 3, 8, 7, 5, 6, 1, 
swapping l:5 and r:1
2, 4, 3, 8, 7, 1, 6, 5, 
swapping l:5 and r:1
calling quickSort on 5 and 4
calling quickSort on 6 and 7
2, 4, 3, 8, 7, 5, 6, 1, 
swapping l:6 and r:1
2, 4, 3, 8, 7, 5, 1, 6, 
swapping l:6 and r:1
calling quickSort on 6 and 5
calling quickSort on 7 and 7
2, 4, 3, 8, 7, 5, 6, 1, 
BUILD SUCCESSFUL (total time: 1 second)

我如何使算法與pivotIndex一起用作a.length的任何索引0 to a.length

您可以在開始排序之前簡單地將所選的樞軸與數組中的第一個元素交換,這樣它將完全像以前一樣工作。

int l = start;
int r = end;

this.swap(a, choosePivot(), start); 
int pivotIndex = start; 

如果選擇從旋轉任意元素開始,則必須更改分區循環的行為。 請參見下面的代碼:

/* Selecting the pivot to be a random-ish element
   and pivotIndex to be beginning, since we don't know
   where it will be until we loop through the list */
int pivot = a[someInt];
int pivotIndex = begin-1;
//have to keep track of where the pivot actually is in the list
int currentPivotIndex = someInt;

for(int i = begin; i <= end; i++) {
    if(a[i] <= pivot) {
        //for each element less than the pivot
        //the pivotIndex moves by one
        pivotIndex++;
        //place the element to the left of the pivot
        this.swap(a, pivotIndex, i);
        //update currentPivotIndex if needed
        if(a[pivotIndex] == pivot) {
            currentPivotIndex = pivotIndex;
        }
    }
}
//put the pivot in its place
this.swap(a, pivotIndex, currentPivotIndex);

這是一些奇怪的行為,很可能是由您的樞軸元素參與分區引起的。

輸出的第一行表示swapping l:8 and r:4但它應該已經swapping l:8 and r:3 因為4是樞軸元素,它既不屬於左側的分區,也不屬於右側的分區。 它是分區中間的元素。 分區期間必須將其隔離。

要解決此問題,請在選擇樞軸后將其移到末尾。 即,第一件事,用數組的最后一個元素替換ivot。 因此,您可以將其與分區過程隔離。 然后,以l = start and r = end - 1開始while循環,因為end當前是樞軸。 不要管它。 完成分區后,將樞軸還原到兩個分區的中間。 中間將是lr相遇的地方。

我相信按照上述方法可以解決您的問題。 讓我知道是否可以。

沒有直接關系,但是您對樞軸元素的選擇會對快速排序的性能產生巨大影響。 使用其當前版本,可能會遇到最壞情況( O(n^2) )。 最簡單的是,您可以隨機選擇它,這很可能帶來O(nlogn)復雜性。

暫無
暫無

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

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