快速排序

【1】快速排序

快速排序是由托尼。霍尔(英文名C. A. R. Hoare,英国人,计算机领域爵士,同时是文科生获图灵奖者之一)于1962年提出的一种划分交换排序。

快速排序采用的是一种分治策略。快速排序经典之处在于它的排序思想。

所谓分治就是分而治之,从字面意思即可理解为:复杂问题简单化,简单问题重复化,重复问题高效化。所以,相比其它排序算法更快速。

而书面解释为:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地处理这些子问题,然后将这些子问题的解组合为原问题的解。

快速排序是一种不稳定的排序(参见随笔《常用排序算法稳定性分析》)。

快速排序是时间复杂度是O(nlogn)。

【2】排序逻辑

设要排序的数组是A[0]~A[N-1]。(下面的例子中A[0]所为哨兵位,所谓哨兵位,即就是临时寄存关键数据位置)

首先任意选取一个数据(通常选用第一个数据,在示例中从A[1]开始)作为关键数据,然后将所有比它大的数都放到它后面,所有比它小的数都放到它前面,这个过程称为一趟快速排序。

一趟快速排序的算法是:

<1>设置两个变量i, j,排序开始的时候:i = 1, j = N-1;

<2>以第一个数组元素(示例中即A[1])作为关键数据,赋值给A[0];

<3>从j开始向前搜索,即由后开始向前搜索(--j),找到第一个小于关键数据A[0]的值A[j], A[i] = A[j];

<4>从i开始向后搜索,即由前开始向后搜索(++i),找到第一个大于关键数据A[0]的值A[i], A[j] = A[i];

<5>重复3,4,5步,直到 i == j;

(注意:只有当i == j时,才可以完全确定当前关键数据可以插入的位置,即就是满足比关键数据小的值全部置于其前,比关键数据大的值全部置于其后。)

【3】排序图解(借用百度图片)

该图片很形象,全神贯注,仔细观察:

【4】C++实现排序代码

(1)C++实现排序详细测试过程示例代码:

  1 #include<iostream>
  2 using namespace std;
  3 #define   MAXSIZE   10
  4 
  5 void PrintArr(int ar[],int n)
  6 {
  7     for(int i = 0; i < n; ++i)
  8     {
  9         cout<<ar[i]<<" ";
 10     }
 11     cout<<endl;
 12 }
 13 
 14 int nCount = 0;
 15 
 16 int Partition(int br[], const int left, const int right)
 17 {
 18     ++nCount;
 19     cout<<""<<nCount<<"趟排序过程如下:"<<endl;
 20     int i = left, j = right;  
 21     cout<<"left = "<<left<<endl;
 22      br[0] = br[left];    //注意哨兵位的作用:暂存本趟排序的关键数据
 23     cout<<"关键字:"<<br[0]<<endl;
 24     cout<<"调整前顺序:"<<endl;
 25     PrintArr(br, MAXSIZE);
 26     while(i < j)
 27     {
 28         while(i < j && br[j] > br[0])   //从末尾开始
 29         {
 30             --j;      //前移一位
 31         }
 32         br[i] = br[j];  //比关键字小的前置
 33         cout<<"比当前关键字大者调整结果:"<<endl;
 34         PrintArr(br, MAXSIZE);
 35         while(i < j && br[i] <= br[0])  //从前端开始
 36         {
 37             ++i;    //后移一位
 38         }
 39         br[j] = br[i];  //比关键字大的后置
 40         cout<<"比当前关键字小者调整结果:"<<endl;
 41         PrintArr(br, MAXSIZE);
 42     } 
 43     br[i] = br[0];  //插入关键字
 44     PrintArr(br, MAXSIZE);
 45     cout<<"i = "<<i<<endl;
 46     cout<<"本趟结束"<<endl;
 47     return i;
 48     
 49 }
 50 
 51 void Quicksort(int br[],const int left,const int right)
 52 {
 53     if(left < right)
 54     {
 55         int mid = Partition(br, left, right);
 56         Quicksort(br,left,mid-1);
 57         Quicksort(br,mid+1,right);
 58     }
 59 }
 60 
 61 void Quicksort(int br[],int n)
 62 {
 63     Quicksort(br, 1, n);
 64 } 
 65 
 66 void  main()
 67 {
 68     int ar[MAXSIZE] = {0, 14, 2, 58, 69, 100, 50, 26, 65, 97}; 
 69     cout<<"排序前原数组"<<endl;
 70     PrintArr(ar, MAXSIZE);   
 71     Quicksort(ar, MAXSIZE-1);   
 72     cout<<"排序后数组排序"<<endl;
 73     PrintArr(ar, MAXSIZE);
 74 
 75 }
 76 /*
 77 排序前原数组
 78 0 14 2 58 69 100 50 26 65 97
 79 第1趟排序过程如下:
 80 left = 1
 81 关键字:14
 82 调整前顺序:
 83 14 14 2 58 69 100 50 26 65 97
 84 比当前关键字大者调整结果:
 85 14 2 2 58 69 100 50 26 65 97
 86 比当前关键字小者调整结果:
 87 14 2 2 58 69 100 50 26 65 97
 88 14 2 14 58 69 100 50 26 65 97
 89 i = 2
 90 本趟结束
 91 第2趟排序过程如下:
 92 left = 3
 93 关键字:58
 94 调整前顺序:
 95 58 2 14 58 69 100 50 26 65 97
 96 比当前关键字大者调整结果:
 97 58 2 14 26 69 100 50 26 65 97
 98 比当前关键字小者调整结果:
 99 58 2 14 26 69 100 50 69 65 97
100 比当前关键字大者调整结果:
101 58 2 14 26 50 100 50 69 65 97
102 比当前关键字小者调整结果:
103 58 2 14 26 50 100 100 69 65 97
104 比当前关键字大者调整结果:
105 58 2 14 26 50 100 100 69 65 97
106 比当前关键字小者调整结果:
107 58 2 14 26 50 100 100 69 65 97
108 58 2 14 26 50 58 100 69 65 97
109 i = 5
110 本趟结束
111 第3趟排序过程如下:
112 left = 3
113 关键字:26
114 调整前顺序:
115 26 2 14 26 50 58 100 69 65 97
116 比当前关键字大者调整结果:
117 26 2 14 26 50 58 100 69 65 97
118 比当前关键字小者调整结果:
119 26 2 14 26 50 58 100 69 65 97
120 26 2 14 26 50 58 100 69 65 97
121 i = 3
122 本趟结束
123 第4趟排序过程如下:
124 left = 6
125 关键字:100
126 调整前顺序:
127 100 2 14 26 50 58 100 69 65 97
128 比当前关键字大者调整结果:
129 100 2 14 26 50 58 97 69 65 97
130 比当前关键字小者调整结果:
131 100 2 14 26 50 58 97 69 65 97
132 100 2 14 26 50 58 97 69 65 100
133 i = 9
134 本趟结束
135 第5趟排序过程如下:
136 left = 6
137 关键字:97
138 调整前顺序:
139 97 2 14 26 50 58 97 69 65 100
140 比当前关键字大者调整结果:
141 97 2 14 26 50 58 65 69 65 100
142 比当前关键字小者调整结果:
143 97 2 14 26 50 58 65 69 65 100
144 97 2 14 26 50 58 65 69 97 100
145 i = 8
146 本趟结束
147 第6趟排序过程如下:
148 left = 6
149 关键字:65
150 调整前顺序:
151 65 2 14 26 50 58 65 69 97 100
152 比当前关键字大者调整结果:
153 65 2 14 26 50 58 65 69 97 100
154 比当前关键字小者调整结果:
155 65 2 14 26 50 58 65 69 97 100
156 65 2 14 26 50 58 65 69 97 100
157 i = 6
158 本趟结束
159 排序后数组排序
160 65 2 14 26 50 58 65 69 97 100
161 */

【2】中分析逻辑的第五条也就是为什么while(i < j ) 而不是 if(i <j )的原因提醒(也可以从上面的测试程序第二趟排序结果分析原因。)。

(2)完整快速排序实现代码:

 1 int Partition(int br[], const int left, const int right)
 2 {
 3     int i = left, j = right;  
 4      br[0] = br[left];   
 5     while(i < j)
 6     {
 7         while(i < j && br[j] > br[0])   
 8         {
 9             --j;      
10         }
11         br[i] = br[j];  
12         while(i < j && br[i] <= br[0])  
13         {
14             ++i;   
15         }
16         br[j] = br[i]; 
17     } 
18     br[i] = br[0];  
19     return i;
20     
21 }
22 
23 void Quicksort(int br[],const int left,const int right)
24 {
25     if(left < right)
26     {
27         int mid = Partition(br, left, right);
28         Quicksort(br,left,mid-1);
29         Quicksort(br,mid+1,right);
30     }
31 }
32 
33 void Quicksort(int br[],int n)
34 {
35     Quicksort(br, 1, n);
36 } 

关于快速排序的代码,可以有很多种写法,个人认为,此种写法比较好理解,并且易于阅读。

 

Good Good Study, Day Day Up.

顺序  选择  循环  坚持  总结

posted @ 2013-01-11 23:45  kaizenly  阅读(3308)  评论(0编辑  收藏  举报
打赏