Quicksort经验分析StackOverflowError

时间:2018-04-14 00:46:17

标签: java algorithm recursion quicksort

我正在尝试对Quicksort执行分析,但我遇到了一个不一致的StackOverflowError。我相信这可能是由于更高数据集的未绑定递归,但我无法弄清楚如何修复它。我的分区也可能已关闭,但调试对我来说效果不佳。

我正在使用的数据集是一组随机生成的大小为10,000的int数组,使用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;
}

1 个答案:

答案 0 :(得分:3)

我不打算尝试调试你的代码。 (首先,你没有提供MCVE ......甚至是堆栈跟踪。)

但是,请考虑一下:

  • Quicksort是一种递归算法,通过将排序问题“划分”为两个较小的排序问题,直到问题微不足道为止。这是分区步骤。
  • 如果您正在排序N个元素并且正确每次将排序问题分成两半,那么您只需要将 2 N(或更少)分区记录到归结为排序一个元素的(微不足道的)问题。

然后从Java的角度来看:

  • StackOverflowError意味着您的递归过深。

所以...... 没有查看代码 ...几乎可以肯定的是,问题在于您实施分区的方式。那是你应该集中注意力的地方。

我建议如下:

  • 注意代码,看看你是否可以找出分区没有选择正确的分区边界的原因;即低,π和嗨。
  • 使用调试器查看正在执行的代码
  • 添加跟踪图以查看low,pi和hi的值是什么,以及它们随算法的进展而变化的方式。

另一点需要注意的是,经典的快速排序有一个边缘情况,分区的选择可以导致O(N 2 )而不是O(NlogN)行为;见https://en.wikipedia.org/wiki/Quicksort#Worst-case_analysis。这对应于排序N个元素需要N深度递归的情况。这将导致Java中的StackOverflowError问题,因为N足够大。