简体   繁体   中英

Quicksort Empirical Analysis StackOverflowError

I'm attempting to perform an analysis on Quicksort but I'm running into an inconsistent StackOverflowError. I believe it's probably due to unbound recursion with higher data sets but I can't figure out how to fix it. My partition might also be off but debugging hasn't worked out too well for me.

The data set I'm using is a set of randomly generated int arrays of size 10,000 using a pivot (arr[0])

Exception in thread "main" java.lang.StackOverflowError
    at AlgorithmTiming.quickSort(AlgorithmTiming.java:78)
    at AlgorithmTiming.quickSort(AlgorithmTiming.java:82)

private int[] quickSort(int[] arr, int low, int high, int pivotType){

    if (low < high)
    {
        /* pi is partitioning index, arr[pi] is
        now at right place */
        int pi = partition(arr, low, high, pivotType);

        // Recursively sort elements before
        // partition and after partition
        quickSort(arr, low, pi-1, pivotType);
        quickSort(arr, pi+1, high, pivotType);
    }
    return arr;
}
private int partition(int arr[], int low, int high, int pivotType)
{
    Random rand = new Random();
    int pivot = arr[0]; //Default Pivot
    if(pivotType == 2) pivot = arr[0] + arr[arr.length / 2] + arr[arr.length-1]; //Median Pivot
    else if(pivotType == 3) pivot = arr[rand.nextInt(arr.length)]; //Random Pivot

    int i = (low-1); // index of smaller element
    for (int j=low; j<=high-1; j++)
    {
        // If current element is smaller than or
        // equal to pivot
        if (arr[j] <= pivot)
        {
            i++;
            // swap arr[i] and arr[j]
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }

    // swap arr[i+1] and arr[high] (or pivot)
    int temp = arr[i+1];
    arr[i+1] = arr[high];
    arr[high] = temp;

    return i+1;
}

I'm not going to attempt to debug your code. (For a start, you did not provide an MCVE ... or even a stacktrace.)

However, consider this:

  • Quicksort is a recursive algorithm that works by "dividing" the sorting problem into two smaller sorting problems until the problems are trivial. This is the partitioning step.
  • If you are sorting N elements and you correctly divide the sort problems in half each time, then you will only need to log 2 N (or less) divisions to get down to the (trivial) problem of sorting one element.

And then from the Java perspective:

  • A StackOverflowError means that your recursion has gotten too deep.

So ... without looking at the code ... it is almost a safe bet that the problem is in the way that you have implemented the partitioning. That's where you should focus your attention.

I would suggest the following:

  • Eyeball the code to see if you can figure out why the partitioning isn't choosing correct partition boundaries; ie low, pi, and hi.
  • Use a debugger to see what the code is doing .
  • Add traceprints to see what the values of low, pi, and hi are, and how they change as the algorithm progresses.

The other thing to note is that classic quicksort has an edge case where the choice of partition can lead to O(N 2 ) rather than O(NlogN) behavior; see https://en.wikipedia.org/wiki/Quicksort#Worst-case_analysis . This corresponds to the case where sorting N elements requires N-deep recursion. That will lead to StackOverflowError problems in Java, for large enough N.

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