我正在做一个快速排序的分配,但它总是抛出一个堆栈溢出排序大列表时(>100.000项目)。堆栈溢出应该表明停止条件是不正确的,但我找不到问题。我真的很感激一些帮助。感谢阅读。我的快速排序:
private void qSort(List<E> items, int low, int high, Comparator<E> comparator) {
// base case
if (low >= high) {
return;
}
// set the pivot (last element)
E pivot = items.get(high);
int leftPointer = low;
int rightPointer = high;
while (leftPointer < rightPointer) {
// we move the left pointer until we find a value that is bigger than the pivot
while (leftPointer < rightPointer && comparator.compare(items.get(leftPointer), pivot) <= 0) {
leftPointer++;
}
// we move the right pointer until we find a value that is smaller than the pivot
while (leftPointer < rightPointer && comparator.compare(items.get(rightPointer), pivot) >= 0) {
rightPointer--;
}
// swap the values at the pointers
swap(items, leftPointer, rightPointer);
}
// at this point, leftPointer and rightPointer are equal and we need to swap the item at the pointers with the pivot
swap(items, leftPointer, high);
// now we have the pivot is in the correct position
// we continue recursively sorting the left side of the pivot, (not including the pivot, because its already in its final position)
qSort(items, low, leftPointer - 1, comparator);
// and the right side of the pivot
qSort(items, leftPointer + 1, high, comparator);
}
字符串
我尝试了各种不同的实现,没有一个工作。我试图增加堆栈大小。
2条答案
按热度按时间jm2pwxwz1#
如果你的数据包含排序的运行,那么
n
项的快速排序将需要O(n)
堆栈帧。即使只有一些排序的运行,这也可能是一个问题。有几种解决方案。最简单的方法是在使用它之前简单地将枢轴与随机元素交换。现在您将在生成
O(n)
伪随机选择时执行O(n)
工作。但是现在几乎不可能触发快速排序的潜在病态行为。目前最常用的解决方案是使用另一种排序算法。Timsort是一种流行的选择,因为它的最坏情况行为是
O(n log(n))
,但它可以在许多常见的真实的世界场景中找到并利用排序序列来获得时间O(n)
。hrirmatl2#
我在on my blog前写过关于实现快速排序的陷阱。看看你的实现:
Job
类只是数组“切片”/范围(两个整数:开始时,推送Job(0,n),其中n是数组长度,然后通过推送作业进行“递归调用”(from,to)。迭代实现将完全避免堆栈溢出,但您可能仍然希望限制辅助空间的使用-为此,请首先推送较大的作业。这背后的基本原理是,我们希望较小的作业位于顶部,因为我们可以使用较少的辅助空间完成它们;可以证明,如果您这样做,您的作业堆栈将最多具有O(log n)大小。如果你可以自由地实现另一种排序算法,我推荐合并排序,我认为这是最简单的有效排序算法(假设你允许使用线性辅助空间)或堆排序(这是就地排序,也达到了O(n log n)的时间复杂度,但仍然很简单)。