1 回答
TA贡献1797条经验 获得超6个赞
如果数据已经按顺序排列,则使用 arr[high](或 arr[low])会导致最坏情况下的堆栈空间开销为 O(n),这会溢出堆栈。第二个示例使用中间元素 (arr[low +(高-低)/2]),它将为已排序的数据或已反向排序的数据提供最佳大小写堆栈空间开销。
将堆栈空间开销限制为O(log(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分区方案更快:
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;
}
}
}
添加回答
举报