简体   繁体   中英

Inconsistent Quicksort StackOverflowError

I'm working on a quicksort problem for arrays of only increasing integers. The pivot choice in this routine is always the first element of the subarray (as dictated by the problem), and at a certain point I expected this to cause a StackOverflowError. The weird thing is, it doesn't work for problems of size n = ~25,000 thru ~404,300, but it works for n much greater than that. Even when I seed the input of the array, it fluctuates to sometimes working for n = 10,000 and sometimes not working.

Here are some results I got (the time is in seconds):

10,000: .077

20,000: .282

~25,000 - ~404,300: SOE

405,000 - 3.169

410,000 - 1.632

450,000 - .098

500,000 - .059

5,000,000 - .634

10,000,000 - 1.337

100,000,000 - 18.613

Any ideas what would cause this? Code below.

Thanks in advance.

public static void main(String[] args) {
    int arraySize = 1000000;
    int[] a = new int[arraySize];
    Random gen = new Random();

    gen.setSeed(0);
    a[0] = gen.nextInt(arraySize * 10);
    for (int i = 1; i < arraySize; i++) {
        a[i] = a[i - 1] + gen.nextInt(arraySize / 10);
}


private static void quickSort(int[] a, int lo, int hi) {
    if (hi <= lo) return;
    int j = partition(a, lo, hi);
    quickSort(a, lo, j - 1);
    quickSort(a, j + 1, hi);
}

private static int partition(int[] a, int lo, int hi) {
    int i = lo, j = hi + 1;
    int pivot = a[i];
    while (true) {
        while (a[++i] > pivot) if (i == hi) break;
        while (pivot > a[--j]) if (j == lo) break;
        if (i >= j) break;
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    int temp = a[lo];
    a[lo] = a[j];
    a[j] = temp;
    return j;
}

I think your partition method is incorrect (but I can be wrong, I've only skimmed the code), so the data is not partitioned correctly resulting in many more recursive calls causing the stack to overflow.

I would suggest you add a print line to the quicksort method which prints out its arguments so you can convert it to a graph of lines, where the X value is the invocation number (ie line 1 is for the first call, line 2 is for the next call etc), and a line is drawn (X, Y1)-(X,Y2) where Y1 is the first value, and Y2 is the second.

My guess is that you will very easily now see what goes wrong (perhaps lower the amount to sort).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM