当我尝试使用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)
由于
答案 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;
}