我要为java编写一个快速排序方法,在本地交换条目,这意味着没有辅助数组来存储东西,并且交换是就地完成的。所以我使用了一些变量来帮助跟踪“低”“hi”和“pivot”指针的位置。
当我运行测试时,它会给我Stack Overflow
错误。但是当我在main()
上使用一些简单的测试数组运行它时,例如:
int[] A = { 0, 0, 1, 1, 0};
它给了我正确的结果。
我猜这个bug(大概是一个无限循环)只是由一些特殊情况触发,但我找不到它。
这是我的代码。
public static void quicksort( int[] A, int low, int hi ){
int len = hi - low + 1;
if (len < 2){ // base case 1
return;
}
else if(len == 2){ // base case 2 (bug-prone now)
if(A[low]<=A[hi]){
return;}
}
else{ // start scanning and swapping and recursing
int pivot = low; //the index of pivot
while(len>1){ // as long as the pivot is not at where it should be...scan and swap
// pivot = low; // updating...unnecessary?
while(pivot<hi){ // check on the right
if (A[pivot]<=A[hi]){
hi--;
}else{
break;
}
}
if(A[pivot]>A[hi]){ //now swap pivot and hi;
int holder=A[pivot];
A[low]=A[hi];
A[hi]=holder;
pivot=hi; // update pointers
low++;
}
while(pivot>low){ // check on the left
if (A[pivot]>=A[low]){
low++;
}else{
break;
}
}
if(A[pivot]<A[low]){ //now swap pivot and low;
int holder=A[pivot];
A[hi]=A[low];
A[low]=holder;
pivot=low;
hi--; // update pointers
}
len = hi - low + 1; // update len for the loop check
}
// now the pivot is in the right position...split and recurse.
quicksort(A, 0, pivot-1); // recurse on the left
quicksort(A, pivot+1, A.length-1); // recurse on the right
} // the end of the else case.
}
答案 0 :(得分:0)
据我所知,StackOverflow错误不能仅由无限循环引起...因为它不消耗内存。递归调用,所以我认为你的问题是你的算法有太多的递归调用(最后两次发生)。尝试更改基本情况以避免这种情况(例如,当长度小于10时使用另一种排序算法,或类似的东西)。
答案 1 :(得分:0)
这是因为您方法结束时的两次递归调用会再次对整个数组进行排序,而不是仅在low
和high
之间。您需要将递归调用限制在底端的low
和顶端的high
。
答案 2 :(得分:0)
尝试将快速排序方法分解为多个小方法,之后将提高可读性。
此外,StackOverflow异常意味着堆栈已满,无法进行进一步的方法调用。查看代码中您调用方法的位置。我最后看到两个地方:
// now the pivot is in the right position...split and recurse.
quicksort(A, 0, pivot-1); // recurse on the left
quicksort(A, pivot+1, A.length-1); // recurse on the right
请调试在这些函数中传递的值是什么。
此外,如果您也可以粘贴测试用例的代码,那将是很好的。