QuickSort:更改枢轴元素会导致StackOverflow

时间:2019-10-22 09:21:37

标签: java algorithm stack-overflow quicksort

尝试使用Hoare分区方案实现QuickSort,但是我遇到一个问题,无论数据大小如何,更改数据透视表的索引都会导致溢出。代码:

public void quickSort(int[] l, int min, int max){
    if (min < max){
        int p = partition(l, min, max);
        quickSort(l, min, p);
        quickSort(l, p+1, max);
    }
}
public int partition(int[] l, int min, int max){
    int pivot = l[min];
    int i = min - 1;
    int j = max +1;
    while(true){
        do{
            i++;
        }while(l[i] < pivot);
        do{
            j--;
        }while(l[j] > pivot);

        if (i >= j) {
                return j;
        }
        //Swap
        int temp = l[i];
        l[i] = l[j];
        l[j] = temp;
    }

}

此实现选择低索引(此处命名为min)作为枢轴元素,并且效果很好。但是,将枢轴元素更改为任何其他索引都会导致StackOverflow错误,无论要排序的数组大小如何。 (错误涉及第3行,其中调用了partition())我最好在(min,max)范围内随机选择枢轴元素。是什么原因造成的?

编辑: 使用的数组生成如下:

public static int[] generateRandomArray(int size, int lower, int upper){
    int[] random = new int[size];
    for (int i = 0; i < random.length; i++) {
        int randInt = ThreadLocalRandom.current().nextInt(lower, upper+1);
        random[i] = randInt;
    }
    return random;
}

在一种溢出情况下,我使用了以下方法:

genereateRandomArray(10, 0, 9);

对于某些具体示例,运行上面的代码,但将枢轴元素更改为l [max-1]或l [min + 1],l [min + 2]等,就可以使我得到StackOverflow。

我的问题的解决方案是用户MBo指出将枢轴元素交换到数组的第一个索引,因为算法本身依赖于枢轴位于索引0。这就是我所忽略的。 (int i = min-1;但是正确,并且保持这种状态。)

2 个答案:

答案 0 :(得分:1)

我们可以看到,在第一步i等于min时,枢轴元素与其自身的比较失败,并且增量没有更多发生:

int pivot = l[min];
    int i = min - 1;
...
 do{
            i++;
        }while(l[i] < pivot);

将枢纽元素从比较(int i = min;)中排除,并与分区1交换(似乎l[j]),最后

答案 1 :(得分:0)

使用透视的中间值对我有用。这是一个完整的示例:

    public static void quickSort(int[] l, int min, int max){
        if (min < max){
            int p = partition(l, min, max);
            quickSort(l, min, p);
            quickSort(l, p+1, max);
        }
    }

    public static int partition(int[] l, int min, int max){
        int pivot = l[(min+max)/2];
        int i = min - 1;
        int j = max + 1;
        while(true){
            do{
                i++;
            }while(l[i] < pivot);
            do{
                j--;
            }while(l[j] > pivot);

            if (i >= j) {
                    return j;
            }
            int temp = l[i];
            l[i] = l[j];
            l[j] = temp;
        }
    }

    public static int[] generateRandomArray(int size, int lower, int upper){
        int[] random = new int[size];
        for (int i = 0; i < random.length; i++) {
            int randInt = ThreadLocalRandom.current().nextInt(lower, upper+1);
            random[i] = randInt;
        }
        return random;
    }

    public static void main(String[] args) {
        int[] A = generateRandomArray(10, 0, 9);
        long bgn, end;
        bgn = System.currentTimeMillis();
        quickSort(A, 0, A.length-1);
        end = System.currentTimeMillis();
        for(int i = 1; i < A.length; i++){
            if(A[i-1] > A[i]){
                System.out.println("failed");
                break;
            }
        }
        System.out.println("milliseconds " + (end-bgn));
    }