繁体   English   中英

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

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

仅当数组不是随机数组时,我的快速排序算法才会对较大的n值失败。 我试过在各种数组上使用该算法。 当我使用数字的随机数组(对于n的任何值)时,它可以正常工作,但是对于包含相同值或以升序或降序排列的值的数组,它会失败。 而且这也仅在n大约为6000时才有效。(当n <5000时,它可以完美工作)

我已经尝试过使用其他版本的quicksort。 使用while循环而不是递归的循环,它可以完美地工作。 就像我已经说过的那样,仅当非随机数组的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);
    }

上面我有我的快速排序算法。 如果n> 6000(并且数组不是随机的)失败。

以下是适用于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;
    }

终端特别在两行显示错误。 (在第一个quicksort方法中,我标记为错误的行)。

如果数据已经整理好,则使用arr [high](或arr [low])会导致最坏情况下O(n)的堆栈空间开销,从而使堆栈溢出。 第二个示例使用中间元素(arr [low +(high-low)/ 2]),这对于已排序的数据或已反向排序的数据将具有最佳的堆栈空间开销。

将分区空间开销限制为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);
}

如果有兴趣,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