【问题标题】:Quicksort Stack overflow error快速排序堆栈溢出错误
【发布时间】:2015-06-06 06:03:20
【问题描述】:

在练习考试时,我遇到了一个(对我而言)关于快速排序的奇怪问题。

我的实现:

    public void quicksort(int l, int r)
{
    if(l<r && l>0 && r<=array.length-1)
    {
        int pivot = array[pivot(l, r)];
        int i = l;
        int j = r;
        if(j==i+1)
        {
            if(array[i]>array[j])
            {
                System.out.println(array[i]+"<->"+array[j]);
                int help = array[i];      
                array[i] = array[j];  
                array[j] = help;    
            }
        }
        else{ while(i<=j)
            {
                if(array[i]>=pivot && pivot>= array[j])
                {
                    System.out.println(array[i]+">="+pivot+">="+array[j]);

                    int help = array[i];      
                    array[i] = array[j];  
                    array[j] = help;
                    i++;
                    j--;
                }
                else{
                    i++;
                }
            }
            if(l<j && j<array.length-1)quicksort(l, j);
            if(i<r)quicksort(i, r);
        }
    }
}

但这在(此处)第 34 行中给了我一个“Java.lang.StackOverflowError: null”。但是,可以通过在第 34 行和第 35 行中将 j 与 j-1 和 i 与 j 交换来避免此错误。我真的尝试了所有想到的东西,但我真的想不出一个解决方案:/

【问题讨论】:

  • 预期的输入输出是什么?
  • 不使用调用堆栈,而是使用堆栈集合。创建一个,因为 java 唯一的堆栈实现是同步的。
  • int 数组“array”是在另一种方法中定义的。 l 是当前列表的左边界元素,r 是右边界元素。两者都是 int 值,因为它们被用作 int 数组的索引。
  • ...为什么它不是函数的参数?
  • 你是指枢轴元素吗?

标签: java recursion stack-overflow quicksort


【解决方案1】:

我认为快速排序有更好的实现,这是我的评论尝试,希望能帮助你更好地记住它:

public static void quickSort(int[] theArray, int left, int right) {
    //we declare 2 variables   
    int i = left;
    int j = right;

    //we calculate a pivot, simply taking the middle value of the array
    int pivot = theArray[(left+right)/2];

    //check that i hasn't gone beyond j (i starts at 0, j starts at array.length)
    while(i<=j){
        //if here, must mean i is less-than or equal to j, so check to see if
        //the array value i is less than our pivot
        while(theArray[i] < pivot){
            //if it is less-than pivot, the value theArray[i] is in correct place
            //so we can increment i to go to next 
            i++;
        }
        //now do exactly same thing for j, however, j starts at array.length, so decrement
        while(theArray[j] > pivot){
            j--;
        }
        //if we are here, it likely means we need to swap values
        //check that i hasn't gone beyond j
        if(i<=j){
            //simple swap
            temp = theArray[i];
            theArray[i] = theArray[j];
            theArray[j] = temp;
            //we just swapped values, so we don't need to check them again, so continue
            i++; 
            j--;
        }
    }
    //now check if parameter left is < j 
    //if left has gone beyond j, it means we no longer need to further sort
    if(left<j){
        //rinse and repeat
        quickSort(theArray, left, j);
    //and check that i is still less than right parameter 
    }if(i < right){
        //rinse and repeat
        quickSort(theArray, i, right);
    }

}

用法:

//you can amend this code so you don't have to pass in an array
quickSort(theArray, 0, theArray.length-1);

一旦您了解了快速排序的目的,这将相当简单。不要为此感到压力,休息 15 分钟,观看算法的图形表示,并思考代码应该如何表现以及它试图实现什么。回到这里,看看代码,然后开始实现它。冲洗并重复!祝你好运!

另外(不确定你的考试布局如何),但你也可以提到,为了保证 O(n log n) 的运行时间足够接近,你真的应该事先shuffle the array。

【讨论】:

  • 理解快速排序不是我的问题。我的问题是递归没有做它应该做的事情,奇怪的是你的代码给了我和我一样的错误。无论如何,谢谢。
  • 没关系。现在它正在做它应该做的事情。只需在递归周围添加括号,两个示例(我的和你的)都可以正常工作。
  • 这很奇怪,但我很高兴你明白了。您正在运行什么 JDK 版本以及如何编译代码?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
  • 2015-12-02
  • 2015-08-05
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多