C ++在quicksort函数中获取StackOverflow错误

时间:2014-03-09 18:05:51

标签: c++ algorithm sorting quicksort

当我尝试使用quicksort对大型数组进行排序时,我收到stackoverflow错误,并且此数组按降序排列。我想使用下面的代码按升序对其进行排序:

int partition_lastElementPivot(int * arr, int lo, int hi)
{
    int x = arr[hi];
    int i = lo - 1;
    for (int j = lo; j < hi; j++)
    {
        if (arr[j] <= x)
        {
            i++;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    int temp = arr[hi];
    arr[hi] = arr[i + 1];
    arr[i + 1] = temp;

    return i + 1;
}

void quicksortLastElementPivot(int*arr, int lo, int hi)
{
    if (lo<hi)
    {
        int mid = partition_lastElementPivot(arr, lo, hi);
        quicksortLastElementPivot(arr, lo, mid - 1);
        quicksortLastElementPivot(arr, mid + 1, hi);
    }
}

当我随机生成任何大小的数组时,这个代码工作正常,假设大小为5000.但是当我生成一个大小为5000的数组按降序排序然后尝试使用此代码排序时,我得到一个stackoverflow错误。 C ++是否限制了堆栈可用的内存,为什么会发生这种情况。

int arr[5000];
int count = 5001;
for(int i=0; i<5000; i++)
{
    arr[i] = count;
    count--;

}
quicksortLastElementPivot(arr, 0, 4999)

由于

3 个答案:

答案 0 :(得分:2)

Quicksort有一个真正可怕的最坏情况表现,正如你在这里发现的那样。它在堆栈深度为5000时调用自己。This Wikipedia article对该主题进行了很好的讨论。特别是,它提到了tail recursion作为堆栈溢出问题的解决方案。

简而言之,这意味着,不是最后一次调用quicksortLastElementPivot,而是紧接着返回,只需循环回到函数的开头。这具有相同的效果,但尾递归不会增加堆栈大小。为此,您必须确保使用传统递归首先对两个分区中较小的分区进行排序,然后通过尾递归对较大的分区进行排序。这样的事情(未经测试!):

void quicksortLastElementPivot(int*arr, int lo, int hi)
{
TailRecurse:
    if (lo<hi)
    {
        int mid = partition_lastElementPivot(arr, lo, hi);
        if (mid < (lo + hi) / 2)
            { // First partition is smaller
            quicksortLastElementPivot(arr, lo, mid - 1); // Sort first partition
            lo = mid + 1; goto TailRecurse;              // Sort second partition
            }
        else
            { // Second partition is smaller
            quicksortLastElementPivot(arr, mid + 1, hi); // Sort second partition
            hi = mid - 1; goto TailRecurse;              // Sort first partition
            }
    }
}

答案 1 :(得分:0)

C ++标准没有定义可执行程序的堆栈大小。

此限制通常在项目的make文件或linker-command文件中定义。

根据您的IDE,您也可以在项目设置中找到它(在链接器配置下)。

TonyK 给出的答案在解决最坏情况下快速排序的堆栈使用方面做得非常好(在您的代码中就是这种情况,{{1按逆序排序。)

答案 2 :(得分:0)

#include <iostream>
using namespace std;

void QuickSort(int *arr, int left, int right)
{
int i = left;
int j = right;
int pivot = arr[rand() % (right - left) + left];
while (i < j)
{
    while (arr[i] < pivot)
    {
        i++;
    }
    while (arr[j] > pivot)
    {
        j--;
    }
    if (i <= j)
    {
        swap(arr[i], arr[j]);
        i++;
        j--;
    }
}
if (left < j)
{
    QuickSort(arr, left, j);
}
if (i < right)
{
    QuickSort(arr, i, right);
}
  }
  int main()
 {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
cin >> n;
int *arr = new int[n];

for (int i = 0; i < n; i++)
{
    cin >> arr[i];
}
QuickSort(arr, 0, n - 1);
for (int i = 0; i < n; i++)
{
    cout << arr[i] << " ";
}

delete arr;
}