我正在尝试将c ++中的quicksort算法实现为讲座中的一个项目。当我从递归调用中排除枢轴时,该程序运行良好,但是当我在任一递归调用中都包含枢轴时,有时会导致堆栈溢出错误。
该程序仅在特定的数组大小下会发生故障,但是我无法弄清楚它们与错误之间的关系。例如,当我给出40时,该程序就会发生故障,但是对于50来说,它就可以正常工作。
void quicksort(double* arr, int init, int fin) {
if (init == fin) return;
if (init == fin - 1) {
if (arr[init] > arr[fin]) {
double temp = arr[fin];
arr[fin] = arr[init];
arr[init] = temp;
}
return;
}
int smaller = init - 1;
double pivot = arr[fin];
for (int ind = init; ind < fin; ind++) {
if (arr[ind] < pivot) {
smaller++;
double temp = arr[ind];
arr[ind] = arr[smaller];
arr[smaller] = temp;
}
}
arr[fin] = arr[smaller + 1];
arr[smaller + 1] = pivot;
if(smaller>=init) quicksort(arr, init, smaller);
if(smaller+2<=fin) quicksort(arr, smaller + 2, fin);
return;
}
这是有问题的代码。当我这样说时,它工作正常,但是当我更换时会导致错误
if(smaller+2<=fin) quicksort(arr, smaller + 2, fin);
使用
if(smaller+1<=fin) quicksort(arr, smaller + 1, fin);
答案 0 :(得分:2)
if(smaller+1<=fin)
等效于if(true)
(因为smaller+1
始于init
,并且最多递增fin-init
次),因此任何呼叫至少三个元素必定会在那一行递归-如果(例如)所有三个元素都相等,则递归调用可能无法完成任何事情。
答案 1 :(得分:0)
另一种查看方式。假设选定的枢轴元素是分区中的最小值。它将移至范围的开头。
[ 3 5 2 1 4] // supposed we select 3 as the pivot
[ 2 1 3 5 4] // after partitioning
[ 3 5 4] // the recursive call for the right "half"
如果我们再次选择3作为枢轴,则此范围内没有任何变化。因此,当我们再次递归正确的“一半”时,我们处于完全相同的情况。我们尚未取得任何进展,因此递归将继续进行,直到堆栈溢出为止。
在递归调用的范围内省略枢纽保证了我们取得了进展,因此递归最终将终止。