1
0
mirror of https://github.com/Didnelpsun/CS408.git synced 2026-11-03 05:43:42 +08:00

Update 10-sort.md

This commit is contained in:
Didnelpsun
2022-06-05 00:02:56 +08:00
parent 88d4483fad
commit a4efb66094

View File

@@ -149,30 +149,31 @@ void Bubble(int[] a) {
1. 选择最右边的元素值做标杆,把标杆值放入$pivot$变量中。
2. 初始时,令$low$和$high$都指向最左边的元素。其中$low$用于被动向右移动,维护小于标杆值的元素的边界,即每次交换的目标索引,一旦交换$low$就向右移动一个;$high$用于主动向右移动,寻找比标杆值小的元素,一旦找到就与$low$指向元素进行交换。
3. 然后$high$开始移动,判断$high$指向的元素值是否小于$pivot$值,如果不小于就继续向右移动。
4. 当遇到比标杆小的值,$high$指向的值就和$low$指向的值进行交换,交换成功后$low$右移一个,$high$继续右移查找。
5. $high$继续移动,最后$high=pivot$时将基准点元素值与$low$指向值进行交换,该轮排序结束。此时$low$指向的位置就是$pivot$值所应该在的位置。
4. 当遇到比标杆小的值,$high$指向的值就和$low$指向的值进行交换,如果$high$和$low$指向的值为同一个则不进行交换,然后$low$右移一个,$high$继续右移查找。
5. $high$继续移动,最后$high>=pivot$时将基准点元素值与$low$指向值进行交换,该轮排序结束。此时$low$指向的位置就是$pivot$值所应该在的位置。
6. 返回基准点元素所在索引,从而确定排序上下边界,递归继续执行排序。
#### 双边循环快排
分为普通分区方案和$hoare$霍尔分区方案。逻辑基本上一样,只是边界选择方式不同。
1. 先选择个值做标杆,把标杆值放入$pivot$变量中。
1. 先选择个值做标杆,一般为最左边值,把标杆值放入$pivot$变量中。
2. 初始时,令$high$指向序列最右边的值,$low$指向序列最左边的值。
3. 然后从$high$开始,当遇到比标杆大的值时$high--$。
4. 当遇到比标杆小的值,就取出这个值放入当前$low$所指的位置。
5. 然后$high$不动,$low++$开始移动。
6. 若$low$所指向的值比标杆小,$low++$。
7. 若$low$所指向的值比标杆大,则放入当前$high$所指向的位置。
8. 然后$low$不动,$high--$开始移动。回到步骤三开始执行。
9. 当$low=high$时表示$low$和$high$之前的元素都比基准小,$low$和$high$之后的元素都比基准大,完成了一次划分。然后把基准元素放入$low$和$high$指向的位置。
10. 不断交替使用$low$和$high$指针进行对比。对左右子序列进行同样的递归操作即可,从步骤三开始。若左右两个子序列的元素数量小等于一,则无需再划分。
3. 然后从$high$开始不断左移,当遇到比标杆大或等于的值时$high--$。
4. 如果发现比标杆小的值,即$high<pivot$,需要交换,然后$high$不动,$low++$开始移动去找要交换的大于标杆的值。
5. 若$low$所指向的值比标杆小或等于,则$low++$进行寻找。(为什么要加上一个等于标杆值可以继续向右移动的条件?因为标杆值默认是第一个值,即初始化$pivot$跟$low$指向同一个值,如果只能小于标杆值才能继续移动不交换,则在第一个元素时,由于标杆值被初始化赋值为第一个值,则标杆$pivot$值等于$low$值,从而导致$low$值跟$high$值进行交换,导致$pivot$标杆值被交换走了,标杆值变为了最开始最右边的$high$值,导致了排序有问题)
6. 若$low$所指向的值比标杆大,则$low$值与$high$值进行交换。
7. 交换后$low$不动,$high--$开始移动。回到步骤三开始执行。
8. 当$low=high$时表示$low$和$high$之前的元素都比基准小,$low$和$high$之后的元素都比基准大,完成了一次划分。然后把基准元素放入$low==high$指向的位置。
9. 不断交替使用$low$和$high$指针进行对比。对左右子序列进行同样的递归操作即可,从步骤三开始。若左右两个子序列的元素数量小等于一,则无需再划分。
即对序列进行比较,有头尾两个指针,尾指针开始比较向前移动,若指向值比对比值小则要交换,交替让头指针开始移动,否则不改变指针则尾指针继续向前;同理头指针向后移动,若指向值比对比值大则交换,交替让尾指针移动,否则不改变指针则头指针继续向后。最后头尾指针指向一个位置,将对比值插入到当前值,此时一趟完成。
在快速排序算法中,并不产生有序子序列,但每趟排序后会将枢轴(基准)元素放到其最终的位置上。且每一趟下来就会出现一个枢轴元素,其中左边小于枢轴,右边大于枢轴,求快速排序趟数就是找到符合这种性质的元素个数。
[洛穆托分区与霍尔分区比较](https://qastack.cn/cs/11458/quicksort-partitioning-hoare-vs-lomuto
)。
#### 快速排序的性能
由于快速排序使用了递归,所以需要递归工作栈,空间复杂度与递归层数相关,所以为$O($递归层数$)$。