【问题标题】:Quicksort causing stack overflow快速排序导致堆栈溢出
【发布时间】:2013-12-13 18:03:11
【问题描述】:

我已经实现了一个整数数组的快速排序,如下所示:

public void Quicksort(int left, int right)
{
    /* The recursive quicksort algorithm consists of four steps:
     * 1. If there are one or less elements in the array to be sorted, return immediately.
     * 2. Pick an element in the array to serve as a "pivot" point. (Usually the left-most element in the array is used.)
     * 3. Split the array into two parts - one with elements larger than the pivot and the other with elements smaller than the pivot.
     * 4. Recursively repeat the algorithm for both halves of the original array.
     */

    int pivot = dataTable[left];

    int l_hold = left;
    int r_hold = right;

    while (left < right)
    {
        while ((dataTable[right] >= pivot) && (left < right))
            right--;

        if (left != right)
        {
            dataTable[left] = dataTable[right];
            left++;
        }

        while ((dataTable[left] <= pivot) && (left < right))
            left++;

        if (left != right)
        {
            dataTable[right] = dataTable[left];
            right--;
        }
    }

    dataTable[left] = pivot;
    pivot = left;
    left = l_hold;
    right = r_hold;

    if (left < pivot)
        Quicksort(left, pivot - 1);

    if (right > pivot)
        Quicksort(pivot + 1, right);
}

它可以运行在一个由 500 000 个随机生成的整数组成的数组中。 如果我用升序或降序整数填充数组,快速排序会在大约 8800 个元素处导致 *Exception。

我用我的小眼睛窥探,没有明确的原因。你能用你的大量眼睛窥探一个原因吗?我可以去找一个正常运行的快速排序的copypasta,但我宁愿找到导致问题的原因。

该方法适用于作为类的一部分的数组,通常使用 (index 0, last index - 1) 调用。万分感谢!

【问题讨论】:

  • 你的递归太深了。您只有大约 1Mb 的堆栈空间可供使用,并且在使用完之后会出现此错误。随机数组可能很快就会停止递归,因为它将达到相同的数字。由于您的设置方式,每次升序/降序都会执行 值的全部深度。这意味着你递归 层深度。
  • 您可能需要考虑从递归设计转变为迭代设计。我建议看看这个帖子:*.com/questions/159590/…

标签: c# arrays stack-overflow quicksort


【解决方案1】:

您正在经历尾递归。简而言之,C# 编译器并没有很好地处理它。我已经读过,如果您在调试时遇到此问题,您可以尝试在发布模式下进行优化并进行编译,这将缓解问题。

还有更详细的信息here

【讨论】:

    【解决方案2】:

    你需要添加停止条件。

    function() {
    
    if(value == 0) {
    break;
    } else {
     function())
    }
    

    您不能一直调用 Quicksort。它需要停止/中断条件。

    【讨论】: