我已经完成了在C ++中实现Quicksort的任务,并且我已经成功编写了似乎有用的代码。当我测试我的算法失败时,当我在一个包含一百万个元素的二进制文件中对数字进行排序时崩溃了。请注意,我有两个文件,每个文件有一百万个元素。其中一个是未分类的,另一个是"几乎排序",我的算法似乎只在排序"几乎排序"文件。这是我的代码的样子:
int partition(int arr[], int low, int high)
{
int pivotI = low; //pivot index
int pivot = arr[pivotI];
int temp = arr[low];
arr[low] = pivot;
arr[pivotI] = temp;
int partitionI = low;
low++;
while (low <= high)
{
if (arr[low] >= pivot)
{
if (arr[high] <= pivot)
{
temp = arr[high];
arr[high] = arr[low];
arr[low] = temp;
low++;
}
high--;
}
else if (arr[high] <= pivot)
{
low++;
}
else
{
low++;
high--;
}
}
if (low == high)
{
if (arr[low - 1] < pivot)
{
temp = arr[low];
}
else
{
temp = arr[low - 1];
}
}
else
{
temp = arr[high];
}
arr[high] = arr[partitionI];
arr[partitionI] = temp;
return high;
}
void quickSort(int arr[], int left, int right)
{
if (left < right)
{
int p = partition(arr, left, right);
quickSort(arr, left, p);
quickSort(arr, p + 1, right);
}
}
*当我运行说&#34;几乎排序&#34;时,我收到堆栈溢出错误二进制文件。知道为什么会这样吗? 感谢
答案 0 :(得分:1)
如果在快速排序中使用透视值的第一个值,则已排序的列表是更糟糕的情况,因为数据透视将始终是分区中的最低值。这可以大大增加递归深度。每个递归调用都需要堆栈帧上的空间(由参数,局部变量和返回地址组成)。对于一个几乎按百万个数字排序的列表,您可能需要接近一百万个堆栈帧同时处于活动状态。这很容易耗尽可用的堆栈空间并产生错误。
您可以尝试使用不同的数据透视算法来解决此问题,例如三个中位数。
答案 1 :(得分:1)
避免堆栈溢出的一种方法是使用循环和递归的组合。在每个分区()之后的quicksort()中,检查是否(p - left)&lt; =(right - p - 1),并且仅对较小的部分使用递归,然后循环返回以拆分较大的部分。这将最坏情况下的堆栈开销限制为log2(n)。最坏情况的时间复杂度仍为O(n ^ 2)。
使用中位数中位数可以将最坏情况时间复杂度降低到O(n log(n))
http://en.wikipedia.org/wiki/Median_of_medians
但常数因子因素更大,减慢了平均和最佳情况的快速排序。