我正在尝试对一个有100000个元素的数组进行排序,并且所有元素都是相等的。这是我的quickSort代码:
public static void quickSortFirst(int[] arr, int left, int right) {
if (left < right) {
int pivotIndex = partition(arr, left, right);
quickSortFirst(arr, left, pivotIndex - 1);
quickSortFirst(arr, pivotIndex + 1, right);
}
}
private static int partition(int[] arr, int left, int right) {
int pivot = arr[left];
int i = left + 1;
int j = right;
while (i <= j) {
while (i <= j && arr[i] <= pivot) {
i++;
}
while (i <= j && arr[j] > pivot) {
j--;
}
if (i <= j) {
swap(arr, i, j);
}
}
swap(arr, left, j);
return j;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
它可以排序1000和10000个元素没有任何问题对接时,计数的元素上升,它给一个堆栈溢出.我尝试了很多代码,我发现在互联网上关于快速排序,但他们没有解决这个问题.每当我使用100000元素,我得到溢出
2条答案
按热度按时间z31licg01#
使用这样的算法和你的数组值(都是相等的),条件
arr[j] > pivot
永远不会为真,j
永远不会递减。然后
i..j
段的分区将始终是i..(j-2)
,pivot和j
。在递归过程中,堆栈将与数组大小成比例增长,从而触发堆栈溢出。你可以做的一件事是在
(i+j)/2+1
附近设置一个阈值,当所有的arr[j]
都相等时,将j
减小到这个阈值。(我还没有用一个小数组检查极限条件)。这将使pivot大致位于表的中间,堆栈大小需要与数组大小的对数成比例。注意,你仍然会有一个已经排序的数组的堆栈溢出!为了避免这样的事情,你应该在数组中随机获得一个枢轴数,而不是总是第一个项目。
kuuvgm7e2#
您的stackoverflow错误可能来自两个可能的来源:
1.它可能是由无限递归引起的
1.可能是堆栈太小造成的
你的函数调用被存储在内存中的一个叫做the stack的部分。首先,让我们了解栈一般是如何工作的。
堆栈是项的集合(计算机科学中的数据),一个放在另一个的顶部,所以,这个数据结构中的最后一项必须是第一个离开它的项,简言之,它是一个LIFO(后进先出),这是合乎逻辑的,因为一般来说,如果结束符号在函数调用中不为真,则需要将两个新的函数调用添加到处理中,并且在它们的调用者之前对其进行评估。
堆栈至少支持以下操作:
内存堆栈通过处理函数调用自动执行堆栈部分的逻辑。然而,如果问题是代码使用了太多内存,那么您需要将代码转换为迭代代码
https://www.tutorialspoint.com/difference-between-recursion-and-iteration
那么,如何将递归代码转换为迭代工作呢?基本上,你需要一个循环,该循环在堆栈不为空时运行,每当需要新项时,将两侧推入堆栈,并在循环的每一步弹出堆栈顶部。
Javarevisited给出了快速排序的迭代实现:
另一个可能的问题是,你最终得到了一个无限递归,它没有检测到算法实现了它的目的,并继续将函数调用推入堆栈,直到函数调用超出堆栈的限制。在这种情况下,你需要彻底检查递归的结束符号,看看是否一切都实现得很好,如果这是你的问题,我们知道调用树的高度是log2(n),如果n = 100000,那么这个高度是16.61,看起来并不深。