Skip to content

Commit 4c0b1c3

Browse files
committed
排序中添加归并算法的说明和快排得实现。
1 parent 627f657 commit 4c0b1c3

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

_posts/2019-07-28-排序.markdown

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,39 @@ void heapSort(vector<int> & a) {
113113
114114
#### 归并排序 merge sort
115115
116+
在讨论归并排序前,先介绍一个常见的算法设计技巧: 分治算法。分治算法由两个部分组成:
116117
118+
> 分: 递归解决较小的问题。
119+
>
120+
> 治: 然后,从子问题的解构建出原问题的解。
121+
122+
形式上看, 在其代码中包含两个或两个以上的递归调用叫做分治算法,而代码中的只含有一个递归调用不是分治算法。通常子问题是不相交的(也即是没有重叠部分)。
123+
124+
回到归并排序算法中,看看如何处理前面的排序问题:
117125
118126
[81,94,11,96,12,35,17,95,28,58,41,75,15]
119127
128+
基于介绍的分治算法,首先需要做的就是分:
129+
130+
* 分,将问题分解:
131+
132+
第一次分解: 将原问题分成【81,94,11,96,12,35】、【17,95,28,58,41,75,15】两个子问题的排序。
133+
134+
第二次分解: 将原问题分成【81,94,11】【96,12,35】、【17,95,28】【58,41,75,15】4个子问题的排序。
135+
136+
第三次分解: 将原问题分成【81】【94,11】【96】【12,35】、【17】【95,28】【58,41】【75,15】8个子问题的排序。(此时有些递归到达了基准情况,不可再分(如【81】),回等待和其相关的的子问题【94、11】,求解完成进行治的过程)。
137+
138+
第四次分解:将原问题分成【81】、【94】【11】、【96】、【12】【35】、【17】、【95】【28】、【58】【41】【75】【15】。16个子问题的排序
139+
140+
* 治,从子问题的解构建出原问题的解
141+
142+
第一次构建:【81】【11,94】【96】【12,35】、【17】【28,95】【41,58】【15,75】
143+
144+
第二次构建:【11,81,94】【12,35,96】、【17,28,95】【15,41,58,75】
145+
146+
第三次构建:【11,12,35,81,94,96】、【15,17,28,41,58,75,95】
120147
148+
第四次构建:【11,12,15, 17,28,35,41,58,75,81,94,95,96】
121149
122150
```c++
123151
// merge 归并排序的驱动入口
@@ -172,3 +200,41 @@ void merge_conquer(vector<int> & a, vector<int> tmp, long leftPos, long rightPos
172200

173201

174202

203+
```c++
204+
205+
int quickSort_partition(vector<int> &v, int lt , int rt) {
206+
int i = lt, j = rt + 1;
207+
int comparaNum = v[lt];
208+
while (true) {
209+
// while stop with two condition: 1. break 2. v[++i] > compareNum
210+
while (v[++i] < comparaNum) if(i == rt) break;
211+
// while stop with two condition: 1. break 2. v[++j] < compareNum
212+
while (v[--j] > comparaNum) if (j == lt) break;
213+
// (除了lo) index < i 一定满足v[i] < compareNum(因为每次++i的条件就是 v[i] < compareNum)
214+
// 若i = j 则是同一个数 , 不用交换。若 j > i , 则 由于 index < i 一定满足v[i] < compareNum
215+
// 故也不用交换,并且当前的 while 结束因此只剩下 v[lt]的位置有可能是不准确的。
216+
if (i >= j) break;
217+
swap(v[i], v[j]);
218+
}
219+
// 由于 while (v[--j] > compareNum) if (j == lt) break;
220+
// v[j] 有两种可能。 1. v[j] < compareNum , 2. v[j] == compareNum;
221+
// 只有在v[j] < compareNum 才需要交换。
222+
if (v[j] < comparaNum) swap(v[lt], v[j] );
223+
return j;
224+
}
225+
226+
// 核心逻辑部分,对于每个partIndex满足
227+
// index < partIndex : v[index] <= v[partIndex]
228+
// index > partIndex : v[index] >= v[partIndex]
229+
void quickSort(vector<int> &v, int lt, int rt) {
230+
// 当 lt 为最小的元素时,partIndex == lt, partIndex-1 < lt
231+
if (lt >= rt) return;
232+
int partIndex = quickSort_partition(v, lt, rt);
233+
quickSort(v, lt, partIndex -1);
234+
quickSort(v, partIndex+1, rt);
235+
}
236+
237+
```
238+
239+
240+

0 commit comments

Comments
 (0)