【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.
顺序 选择 循环 坚持 总结