Quicksort算法(Cormen)给出了Stackoverflow

时间:2015-10-31 14:18:43

标签: algorithm stack-overflow quicksort

我实现了快速排序算法,该算法在算法导论(Cormen,3rd Edition)7.1中给出了伪代码

当我尝试使用小型数组的算法时,结果为真。但是当我尝试N = 50000并且数组已经像这样排序了; N = {1,2,3,...,50000};

它给出了StackOverflowError。我认为这种情况正在发生,因为该功能可以将自身递归50000次。 QuickSort(A,0,49999)=> QuickSort(A,0,49998)=> QuickSort(A,0,49997)......继续。

我可以解决这个问题吗?或者我应该使用不同的枢轴位置?

这是我的代码;

public void sort(int[] arr){ QuickSort(arr, 0, arr.length - 1); }

private void QuickSort(int[] A, int left, int right){
    if(left < right){
        int index = Partition(A, left, right);
        QuickSort(A, left, index - 1);
        QuickSort(A, index + 1, right);
    }
}

private int Partition(int[] A, int left, int right){
    int pivot = A[right];
    int wall = left-1;
    for(int i=left; i<right; i++){
        if(A[i] <= pivot){
            Swap(A, ++wall, i);
        }
    }
    Swap(A, wall + 1, right);
    return wall + 1;
}

private void Swap(int[] A, int x, int y){
    int keeper = A[x];
    A[x] = A[y];
    A[y] = keeper;
}

1 个答案:

答案 0 :(得分:0)

是的,这个数据透视方案不是排序数组的正确选择。正如您所注意到的,它导致非常不平衡的分区,导致O(N ^ 2)复杂度和非常深的递归级别。
有一些方法可以改善这种行为。 例如,您可以使用随机索引作为pivotIdx = start + rand() % (end-start+1);的枢轴,或选择三个中值方法(索引范围中的第一个,最后一个和中间元素的中位数)。

P.S。避免堆栈溢出的选项 - 首先为较短的段调用递归,然后为较长的段调用递归。

https://en.wikipedia.org/wiki/Quicksort#Choice_of_pivot