merge_sort什么时候击败quick_sort?

时间:2011-11-02 01:23:33

标签: c++ algorithm

SO帖子

When to use merge sort and when to use quick sort?

Quick Sort Vs Merge Sort

维基百科

http://en.wikipedia.org/wiki/Merge_sort

http://en.wikipedia.org/wiki/Quicksort

quick_sort假设最坏情况为O(n ^ 2),但merge_sort假设没有最坏情况且始终为O(n * log N)。我认为它取决于数据集的顺序 - 反向顺序,正向顺序或随机,但是当我运行测试时... quick_sort总是更快。我使用的代码如下:

/*
Needs a reszie function added
*/
#include "c_arclib.cpp"
template <class T> class dynamic_array
  {
  private:
    T* array;
    T* scratch;
  public:
    int size;
    dynamic_array(int sizein)
      {
      size=sizein;
      array = new T[size]();
      }
    void print_array()
      {
      for (int i = 0; i < size; i++) cout << array[i] << endl;
      }
    void merge_recurse(int left, int right)
      {
      if(right == left + 1)
        {
        return;
        }
      else
        {
        int i = 0;
        int length = right - left;
        int midpoint_distance = length/2;
        int l = left, r = left + midpoint_distance;
        merge_recurse(left, left + midpoint_distance);
        merge_recurse(left + midpoint_distance, right);
        for(i = 0; i < length; i++)
          {
          if((l < (left + midpoint_distance)) && (r == right || array[l] > array[r]))
            {
            scratch[i] = array[l];
            l++;
            }
          else
            {
            scratch[i] = array[r];
            r++;
            }
          }
        for(i = left; i < right; i++)
          {
          array[i] = scratch[i - left];
          }
        }
      }
    int merge_sort()
      {
      scratch = new T[size]();
      if(scratch != NULL)
        {
        merge_recurse(0, size);
        return 1;
        }
      else
        {
        return 0;
        }
      }
    void quick_recurse(int left, int right) 
      {  
      int l = left, r = right, tmp;
      int pivot = array[(left + right) / 2];
      while (l <= r)
        {
        while (array[l] < pivot)l++;
        while (array[r] > pivot)r--;
        if (l <= r) 
          {
          tmp = array[l];
          array[l] = array[r];
          array[r] = tmp;
          l++;
          r--;
          }
        }
      if (left < r)quick_recurse(left, r);
      if (l < right)quick_recurse(l, right);
      }  
    void quick_sort()
      {
      quick_recurse(0,size);
      }
    void rand_to_array()
      {
      srand(time(NULL));
      int* k;
      for (k = array; k != array + size; ++k)                                             
        { 
        *k=rand();                                      
        } 
      }
    void order_to_array()
      {
      int* k;
      int i = 0;
      for (k = array; k != array + size; ++k)                                             
        { 
        *k=i;
        ++i;        
        } 
      }
    void rorder_to_array()
      {
      int* k;
      int i = size;
      for (k = array; k != array + size; ++k)                                             
        { 
        *k=i;
        --i;        
        } 
      }
  };
int main()
  {
  dynamic_array<int> d1(1000000);
  d1.order_to_array();
  clock_t time_start=clock();
  d1.merge_sort(); 
  clock_t time_end=clock();
  double result = (double)(time_end - time_start) / CLOCKS_PER_SEC; 
  cout << result;
  }

3 个答案:

答案 0 :(得分:2)

快速排序的最坏情况是当每个递归时pivot元素是数组中的最大或最小元素。在这种情况下,你将不得不进行n-1次递归(你拆分的一个数组总是只有一个元素),它总共给你一个O(n 2 )。

如果您使用已排序的数组并选择第一个或最后一个元素作为枢轴元素,则可以重现最坏情况以进行快速排序。

答案 1 :(得分:1)

合并排序适用于不适合内存的数据,因为每次传递都是线性的,可以读/写到磁盘。在这种情况下,快速排序甚至不是一个选项,尽管两者可以组合在一起 - 快速排序块适合内存,并合并排序这些块直到完成。

答案 2 :(得分:0)

考虑容器类型 - mergesort可以更好地使用链表,因为您可以通过遍历它并将节点分配给备用子列表来将列表拆分为相等的部分;为了快速排序而重新围绕枢轴重新安排事情的工作要多得多。