当我在quicksort算法的递归调用中包含数据透视时,为什么会出现堆栈溢出?

时间:2019-04-11 14:49:25

标签: c++ algorithm sorting quicksort

我正在尝试将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);

2 个答案:

答案 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作为枢轴,则此范围内没有任何变化。因此,当我们再次递归正确的“一半”时,我们处于完全相同的情况。我们尚未取得任何进展,因此递归将继续进行,直到堆栈溢出为止。

在递归调用的范围内省略枢纽保证了我们取得了进展,因此递归最终将终止。