Chinaunix首页 | 论坛 | 博客
  • 博客访问: 260349
  • 博文数量: 84
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 927
  • 用 户 组: 普通用户
  • 注册时间: 2015-03-06 23:00
个人简介

growing

文章分类

全部博文(84)

文章存档

2017年(6)

2016年(61)

2015年(17)

我的朋友

分类: C/C++

2016-04-08 11:45:54

1.传统方法
思路:任意找一个key,begin和end从两头找,begin找大(相对于key),end找小,找到了就交换。完毕之后将key放在中间为boundary,再用两边的区间递归上面的做法,直到元素有序。
  1. int Partition(int *a,int left,int right)
  2. {
  3.     assert(a);
  4.     int begin = left,end = right - 1,key = a[right];
  5.     while(begin < end)
  6.     {
  7.         while(a[begin] < key && begin <= end)
  8.         {
  9.             begin++;
  10.         }
  11.         while(a[end] > key && end >= begin)
  12.         {
  13.             --end;
  14.         }
  15.         if(begin < end)
  16.         {
  17.             swap(a[begin],a[end]);
  18.         }
  19.     }
  20.     if(a[begin] > a[right])
  21.     {
  22.         swap(a[begin],a[right]);
  23.         return begin;
  24.     }
  25.     else
  26.     {
  27.         return right;
  28.     }
  29. }
  30. void QuickSort(int *a,int left,int right)
  31. {
  32.     assert(a);
  33.     if(right > left)
  34.     {
  35.         int boundary = Partition(a,left,right);
  36.         QuickSort(a,left,boundary - 1);
  37.         QuickSort(a,boundary + 1,right);    
  38.     }
  39. }
2.延伸方法(代码较简洁)
思路:定义prev和cur,prev刚开始在cur前一个,两个都在左边,prev往前指向小的,cur往前指向大的,逐次交换直到最后面。

  1. int Partition2(int *a,int left,int right)
  2. {
  3.     assert(a);
  4.     int cur = left,prev = left - 1,key = a[right];
  5.     while(cur < right)
  6.     {
  7.         if(a[cur] < key && (++prev) != cur)
  8.         {
  9.             swap(a[prev],a[cur]);
  10.         }
  11.         ++cur;
  12.     }
  13.     swap(a[++prev],a[right]);
  14.     return prev;
  15. }
  16. void QuickSort2(int *a,int left,int right)
  17. {
  18.     assert(a);
  19.     if(right > left)
  20.     {
  21.         int boundary = Partition2(a,left,right);
  22.         QuickSort(a,left,boundary - 1);
  23.         QuickSort(a,boundary + 1,right);    
  24.     }
  25. }

3.挖坑填数法
原理:找一个key,key的位置为最前(最后也行),key的位置就相当于一个坑,begin从前往后找小,若找到了比key更小的就填补到key的位置,自己的位置就等于有个坑了,再从前往后找小,若找到了比key更小的就填补到上一个坑的位置,重复以上步骤,直到数列有序。
  1. int Partition3(int *a,int left,int right)
  2. {
  3.     assert(a);
  4.     int begin = left,end = right,key = a[right];
  5.     while(begin < end)
  6.     {
  7.         while(a[begin] <= key && begin <= end)
  8.         {
  9.             ++begin;
  10.         }
  11.         if(begin < end)
  12.         {
  13.             a[end] = a[begin];
  14.         }
  15.         while(a[end] >= key && begin <= end)
  16.         {
  17.             --end;
  18.         }
  19.         if(begin < end)
  20.         {
  21.             a[begin] = a[end];
  22.         }
  23.     }
  24.     a[begin] = key;
  25.     return begin;
  26. }
  27. void QuickSort3(int *a,int left,int right)
  28. {
  29.     assert(a);
  30.     if(right > left)
  31.     {
  32.         int boundary = Partition3(a,left,right);
  33.         QuickSort(a,left,boundary - 1);
  34.         QuickSort(a,boundary + 1,right);    
  35.     }
  36. }
4.优化
(1)从上面方法可以看出当选的key越接近数列中最大值或最小值时,递归的次数越多,算法效率越低,所以我们要尽量把key选的适中。以下是三数取中法:

  1. int GetMidIndex(int *a,int left,int right)
  2. {
  3.     assert(a);
  4.     int mid = left -(left - right)/2;
  5.     if(a[left] < a[right])
  6.     {
  7.         if(a[mid] < a[left])
  8.             return left;
  9.         else if(a[mid] < a[right])
  10.             return mid;
  11.         else
  12.             return right;
  13.     }
  14.     else
  15.     {
  16.         if(a[mid] < a[right])
  17.             return right;
  18.         if(a[mid] < a[left])
  19.             return mid;
  20.         else
  21.             return left;
  22.     }
  23. }
(2)
数组长度大时候用快排,排到一定程度,数组变小了之后用插入排序提高效率。
因为直接插入对小区间效率较高。
5.非递归方法

  1. void QuickSort5(int *a,int left,int right)
  2. {
  3.     assert(a);
  4.     stack<int> s;
  5.     if(right > left)
  6.     {

  7.         int boundary = Partition5(a,left,right);
  8.         if(left < boundary - 1)
  9.         {
  10.             s.push(left);
  11.             s.push(boundary - 1);
  12.         }
  13.         if(boundary+1 < right)
  14.         {
  15.             s.push(boundary+1);
  16.             s.push(right);
  17.         }
  18.         while(!s.empty())
  19.         {
  20.             int end = s.top();
  21.             s.pop();
  22.             int begin = s.top();
  23.             s.pop();
  24.             boundary = Partition2(a,begin,end);

  25.             if(begin < boundary - 1)
  26.             {
  27.                 //左边界在下,右边界在上。
  28.                 s.push(begin);
  29.                 s.push(boundary - 1);
  30.             }
  31.             if(boundary + 1 < end)
  32.             {
  33.                 s.push(boundary+1);
  34.                 s.push(end);
  35.             }
  36.         }    
  37.     }
  38. }



阅读(1999) | 评论(0) | 转发(0) |
0

上一篇:body正文标签

下一篇:归并排序及优化思路

给主人留下些什么吧!~~