1
0
mirror of https://github.com/Didnelpsun/CS408.git synced 2026-02-03 19:03:53 +08:00

Update 9-sort.md

This commit is contained in:
Didnelpsun
2022-09-22 23:03:15 +08:00
parent 7fc9a4b155
commit fb409031df

View File

@@ -398,6 +398,9 @@ $n$个元素二路归并排序,归并一共要$\log_2n$趟,每次归并时
基数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
+ 只能对整数进行排序。
+ 元素的移动次数与关键字的初始排列次序无关。
#### 基数的定义
假设长度为$n$的线性表中每个结点$a_j$的关键字由$d$元组$(k_j^{d-1},k_j^{d-2},\cdots,k_j^1,k_j^0)$组成,其中$0\geqslant k_j^i\geqslant r-1\,(0\geqslant i\geqslant d-1)$,其中$r$就是基数。
@@ -473,16 +476,18 @@ $n$个元素二路归并排序,归并一共要$\log_2n$趟,每次归并时
指在排序期间元素全部存放在内存中的排序。除了分配排序,其他的内部排序往往要经过比较和移动。
算法种类|最好时间复杂度|平均时间复杂度|最好时间复杂度|空间复杂度|是否稳定
:-----:|:------------:|:----------:|:------------:|:-------:|:------:
直接插入排序|$O(n)$|$O(n^2)$|$O(n^2)$|$O(1)$|是
冒泡排序|$O(n)$|$O(n^2)$|$O(n^2)$|$O(1)$|
简单选择排序|$O(n^2)$|$O(n^2)$|$O(n^2)$|$O(1)$|否
希尔排序|$?$|$?$|$?$|$O(1)$|否
快速排序|$O(n\log_2n)$|$O(n\log_2n)$|$O(n^2)$|$O(\log_2n)$|否
堆排序|$O(n\log_2n)$|$O(n\log_2n)$|$O(n\log_2n)$|$O(1)$|否
二路归并排序|$O(n\log_2n)$|$O(n\log_2n)$|$O(n\log_2n)$|$O(n)$|是
基数排序|$O(d(n+r))$|$O(d(n+r))$|$O(d(n+r))$|$O(r)$|是
算法种类|最好时间复杂度|平均时间复杂度|最好时间复杂度|空间复杂度|是否稳定|趟数
:------:|:------------:|:------------:|:------------:|:--------:|:------:|:--:
直接插入排序|$O(n)$|$O(n^2)$|$O(n^2)$|$O(1)$|是|$n-1$
希尔排序|$?$|$?$|$?$|$O(1)$|否|$s$
简单选择排序|$O(n^2)$|$O(n^2)$|$O(n^2)$|$O(1)$|否|$n-1$
快速排序|$O(n\log_2n)$|$O(n\log_2n)$|$O(n^2)$|$O(\log_2n)$|否|初始序列
冒泡排序|$O(n)$|$O(n^2)$|$O(n^2)$|$O(1)$|是|初始序列
堆排序|$O(n\log_2n)$|$O(n\log_2n)$|$O(n\log_2n)$|$O(1)$|否|初始序列
二路归并排序|$O(n\log_2n)$|$O(n\log_2n)$|$O(n\log_2n)$|$O(n)$|是|$\log_2n$
基数排序|$O(d(n+r))$|$O(d(n+r))$|$O(d(n+r))$|$O(r)$|是|$r$
+ 每趟排序结束都至少能够确定一个元素最终位置的方法:选择、交换。(插入和归并则不行)
## 外部排序
@@ -544,29 +549,51 @@ $k$路平衡归并:最多只能有$k$个段归并为一个,需要一个输
27 12 1 17 2 9 11 4
```
传统方法从$k$个归并段选出一个最大或最小元素需要对比关键字$k-1$次,而使用$k$路归并的败者树只需要对比关键字$\lceil\log_2k\rceil$次(败者树层数)。
传统方法从$k$个归并段选出一个最大或最小元素需要对比关键字$k-1$次,而使用$k$路归并的败者树只需要对比关键字$\lceil\log_2k\rceil$次(败者树层数,不包括成功结点)。
构建败者树还是需要$n-1$次对比。
### 置换选择排序
如果内存工作区只能容纳$l$个记录,则初始归并段也只能包含$l$条记录,若文件共有$n$条记录,则初始归并段的数量为$r=\lceil n/l\rceil$。
用于构建更长的初始归并段,从而减少归并次数。
假设初始始待排文件为$FI$,初始归并段输出文件为$FO$,内存工作区为$WA$$FO$和$WA$的初始状态为空,$WA$可容纳$w$个记录。置换选择算法的步骤如下:
1. 从$FI$输入$w$记录到工作区$WA$。
1. 从$FI$输入$w$记录到工作区$WA$。
2. 从$WA$中选出其中关键字取最小值的记录,记为$MINIMAX$记录。
3. 将$MINIMAX$记录输出到$FO$中去。
4. 若$FI$不空,则从$FI$输入下一个记录到$WA$中。
5. 从$WA$中所有关键字比$MINIMAX$记录的关键字大的记录中选出最小关键字记录,作为新的$MINIMAX$记录。
6. 重复步骤三到五,直至在$WA$中选不出新的$MINIMAX$记录为止,由此得到一个初始归并段,输出一个归并段的结束标志到$FO$中去。准备输出新的归并段。
6. 重复步骤三到五,如果新输入到$FI$的关键字小于$MINIMAX$的值,则驻留在$WA$中,直至在$WA$中填满选不出新的$MINIMAX$记录为止,由此得到一个初始归并段,输出一个归并段的结束标志到$FO$中去。准备输出新的归并段。
7. 重复步骤二到六,直至$WA$为空。由此得到全部初始归并段。
此时输出的初始归并段可以超过$WA$,且初始归并段长度是不一定相等的。
如$FI$$4,6,9,7,13,11,14,22,30,2,3,19,20,17,23,5,36,12,18,21,39$$WA$长度为$3$$FO$为$4,6,7,9,11,13,14,16,22,30$、$2,3,10,17,19,20,23,36$、$1,5,12,18,21,39$。
如$FI$$4,6,9,7,13,11,14,22,30,2,3,19,20,17,1,23,5,36,12,18,21,39$$WA$长度为$3$$FO$为$4,6,7,9,11,13,14,16,22,30$、$2,3,10,17,19,20,23,36$、$1,5,12,18,21,39$。
^表示中断当前归并段,下一个$FI$开启新的归并段;√表示该$WA$值超过$MINIMAX$值,不能输出到当前$FO$归并段中,只能等待输出到下一个归并段。
FI|4|6|9|7|13|11|14|22|30|2|3|19||20
:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
WA1|4|4|4|7|7|11|11|22|22|22|3√|3√|3|3
WA2||6|6|6|13|13|13|13|30|30|30|19√|19|19
WA3|||9|9|9|9|14|14|14|2√|2√|2√|2|20
MINIMAX|||4|6|7|9|11|13|14|22|30|30|2|3
FO|||4|6|7|9|11|13|14|22|30|^|2|3
FI|17|1|23|5|36|12||18|21|39||||
:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
WA1|17|1√|1√|1√|1√|1√|1|18|18|18
WA2|19|19|23|23|36|12√|12|12|12|39|39|39
WA3|20|20|20|5√|5√|5√|5|5|21|21|21
MINIMAX|17|19|20|23|36|36|1|5|12|18|21|39
FO|17|19|20|23|36|^|1|5|12|18|21|39|^
### 最佳归并树
因为每个归并段的长度不同,所以归并的次序比较重要。
因为现实中的每个归并段的长度不同,所以归并的次序比较重要。
#### 最佳归并树的衡量