1 回答

TA貢獻1797條經(jīng)驗 獲得超6個贊
如果數(shù)據(jù)已經(jīng)按順序排列,則使用 arr[high](或 arr[low])會導(dǎo)致最壞情況下的堆棧空間開銷為 O(n),這會溢出堆棧。第二個示例使用中間元素 (arr[low +(高-低)/2]),它將為已排序的數(shù)據(jù)或已反向排序的數(shù)據(jù)提供最佳大小寫堆棧空間開銷。
將堆棧空間開銷限制為O(log(n))的解決方法是在進行分區(qū)后,檢查哪個部分更小,并且只在較小的部分上使用遞歸,然后循環(huán)回去處理較大的部分(根據(jù)需要更新低或高以排除現(xiàn)在排序的較小部分,然后再循環(huán)回去)。
public static void quicksort(int[] arr, int low, int high)
{
while (low < high) {
int index = partition(arr, low, high);
if((index-low) <= (high-index)){ // avoid stack overflow
quicksort(arr, low, index - 1); //
low = index+1; //
}else{ //
quicksort(arr, index + 1, high); //
high = index-1; //
} //
}
}
public static int partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
int tmp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = tmp;
return (i + 1);
}
如果有興趣,Hoare分區(qū)方案更快:
public static void qsort(int[] a, int lo, int hi)
{
while(lo < hi){
int md = lo+(hi-lo)/2;
int ll = lo-1;
int hh = hi+1;
int p = a[md];
int t;
while(true){
while(a[++ll] < p);
while(a[--hh] > p);
if(ll >= hh)
break;
t = a[ll];
a[ll] = a[hh];
a[hh] = t;
}
ll = hh++;
if((ll - lo) <= (hi - hh)){
qsort(a, lo, ll);
lo = hh;
} else {
qsort(a, hh, hi);
hi = ll;
}
}
}
添加回答
舉報