简体   繁体   English

如何解决较大的n值的快速排序算法? (并且当数组不是随机的时)

[英]How do I fix my quicksort algorithm for larger values of n ? ( and when the array is not random)

My quicksort algorithm fails for larger values of n, and only if the array is not random. 仅当数组不是随机数组时,我的快速排序算法才会对较大的n值失败。 I've tried using the algorithm on various arrays. 我试过在各种数组上使用该算法。 It works fine when I use a random array of numbers (for any value of n), but for an array that contains the same values or values in ascending order or descending order, It fails. 当我使用数字的随机数组(对于n的任何值)时,它可以正常工作,但是对于包含相同值或以升序或降序排列的值的数组,它会失败。 And that too only when n is approximately abov 6000. ( It works perfectly when n is <5000) 而且这也仅在n大约为6000时才有效。(当n <5000时,它可以完美工作)

I've already tried using a different version of quicksort. 我已经尝试过使用其他版本的quicksort。 One that uses a while loop instead of recursion, and it works perfectly. 使用while循环而不是递归的循环,它可以完美地工作。 And like I've said already my algorithm fails only when n is greater than 6000 for a nonrandomized array, for 5000 or below it works well. 就像我已经说过的那样,仅当非随机数组的n大于6000时,我的算法才会失败,对于5000或更低的算法,它会很好地工作。

void quicksort(int a[], int low, int high) {

        if (low < high) {

            int index = partition(a, low, high); // error 
            quicksort(a, low, index - 1);  // error
            quicksort(a, index + 1, high);

        }

    }

int partition(int arr[], int low, int high) {

        int pivot = arr[high];

        int i = low - 1;
        //int j = low;
        for (int j = low; j < high; 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;
            }
        }

        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;
        return (i + 1);
    }

Above I have my quicksort algorithm. 上面我有我的快速排序算法。 The one that fails for n>6000( and when the array is not random). 如果n> 6000(并且数组不是随机的)失败。

And below is the code that worked for all values of n and on any type of array. 以下是适用于n的所有值以及任何类型的数组的代码。



     public void quicksort(int[] data, int low, int high)
   {  // 1 or 0 items are sorted by default
      if(high - low < 1)
         return;

      int left = low;
      int right = high;
      int pivot = data[low + (high - low) / 2];  

      while(left <= right)
      {  // Increment left pointer until left >= pivot
         while(data[left] < pivot)
            left++;

         // Increment right pointer until right <= pivot
         while(data[right] > pivot)
            right--;

         // If left < right; swap values
         if(left <= right)
         {  int temp = data[left];
            data[left] = data[right];
            data[right] = temp;
            left++;
            right--;
         }

      }
      // quick_sort 'lesser values'
      quicksort(data, low, right);

      // quick_sort 'greater values'
      quicksort(data, left, high);
   }

       static int partition(int[] array, int low, int high) {
        int j, temp, i = low + 1;
        Random random = new Random();
        int x = random.nextInt(high - low) + low;
        temp = array[low];
        array[low] = array[x];
        array[x] = temp;
        for (j = low + 1; j <= high; j++) {
            if (array[j] <= array[low] && j != i) {
                temp = array[j];
                array[j] = array[i];
                array[i++] = temp;
            } else if (array[j] <= array[low]) {
                i++;
            }
        }
        temp = array[i - 1];
        array[i - 1] = array[low];
        array[low] = temp;
        return i - 1;
    }

The terminal shows an error in two lines specifically. 终端特别在两行显示错误。 (The lines that I have marked as an error in the first quicksort method). (在第一个quicksort方法中,我标记为错误的行)。

If the data is already in order, then using arr[high] (or arr[low]) results in worst case stack space overhead of O(n), which overflows the stack. 如果数据已经整理好,则使用arr [high](或arr [low])会导致最坏情况下O(n)的堆栈空间开销,从而使堆栈溢出。 The second example, uses the middle element (arr[low + (high-low)/2]), which will have best case stack space overhead for data already sorted or data already reverse sorted. 第二个示例使用中间元素(arr [low +(high-low)/ 2]),这对于已排序的数据或已反向排序的数据将具有最佳的堆栈空间开销。

A workaround to limit stack space overhead to O(log(n)), is after doing partition, check to see which part is smaller, and only use recursion on the smaller part, then loop back to handle the larger part (update low or high as needed to exclude the now sorted smaller part before looping back). 将分区空间开销限制为O(log(n))的一种解决方法是在进行分区之后,检查哪个部分较小,并且仅对较小的部分使用递归,然后循环返回以处理较大的部分(更新为低或根据需要将其设置为高,以便在环回之前排除现在已排序的较小部分)。

public static void quicksort(int[] arr, int low, int high)
{
    while (low < high) {
        int index = partition(arr, low, high);
        if((index-low) <= (high-index)){       // avoid stack overflow
            quicksort(arr, low, index - 1);    //
            low = index+1;                     //
        }else{                                 //
            quicksort(arr, index + 1, high);   //
            high = index-1;                    //
        }                                      //
    }
}

public static int partition(int[] arr, int low, int high)
{
    int pivot = arr[high];
    int i = low - 1;
    for (int j = low; j < high; j++) {
        if (arr[j] <= pivot) {
            i++;
            int tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }
    }
    int tmp = arr[i + 1];
    arr[i + 1] = arr[high];
    arr[high] = tmp;
    return (i + 1);
}

If interested, Hoare partition scheme is faster: 如果有兴趣,Hoare分区方案会更快:

public static void qsort(int[] a, int lo, int hi)
{
    while(lo < hi){
        int md = lo+(hi-lo)/2;
        int ll = lo-1;
        int hh = hi+1;
        int p = a[md];
        int t;
        while(true){
            while(a[++ll] < p);
            while(a[--hh] > p);
            if(ll >= hh)
                break;
            t     = a[ll];
            a[ll] = a[hh];
            a[hh] = t;
        }
        ll = hh++;
        if((ll - lo) <= (hi - hh)){
            qsort(a, lo, ll);
            lo = hh;
        } else {
            qsort(a, hh, hi);
            hi = ll;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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