我正在尝试实现快速排序算法,我选择枢轴作为最右边的元素。但是,当已经对~4000个元素的数组进行排序时,会发生堆栈溢出。这是我的实施:
void quickSortSimpleAscending(int elements[], int startindex, int endindex)
{
int pivot = elements[endindex];
int i = startindex;
int j = endindex;
while (i < j)
{
while (elements[i] < pivot)
i++;
while (elements[j] > pivot)
j--;
if (i <= j)
{
swap(elements[i], elements[j]);
i++;
j--;
}
}
if (startindex < j)
quickSortSimpleAscending(elements, startindex, j);
if (i < endindex)
quickSortSimpleAscending(elements, i, endindex);
}
有没有办法解决这个问题而不使用“三个中位数”的方法? 谢谢!
答案 0 :(得分:2)
首先,很高兴看到您的代码不使用三个中间值来选择枢轴。您只需选择右侧元素作为枢轴。
有没有办法解决这个问题而不使用方法&#34;三个中位数&#34;?
三个中位数本身并不是你得到堆栈溢出的原因。当通过连续和递归调用获得坏分区时,可能发生溢出;也就是说,当枢轴导致左分区比右分区更大时。在具体情况下,如果数组已经排序,那么您将获得n - 1
元素的左分区和零大小的右分区。下次您将获得n - 2
的左侧分区,依此类推。因此,该算法将执行n
递归调用,这将针对适度的堆栈大小而溢出。
为了降低溢出的风险,并且在实践中要避免溢出,解决方案是首先对最小的分区进行排序。使用这种方法,最糟糕的情况将在您获得最佳分区时发生;也就是说,当他们往往是相同的大小。在这种情况下,连续递归调用的最大数量为log(n)
。
我希望这会有所帮助
答案 1 :(得分:0)
实际上,如果不限制递归深度,迟早会出现堆栈溢出。一个常见的解决方法是向函数添加第四个参数以跟踪深度,并在达到特定限制时切换到其他排序算法。