导图社区 《数据结构》第八章-排序
《数据结构》第八章-排序笔记,包括插入排序、交换排序、外部排序、各种内部排序算法的比较及应用、归并排序和基数排序等等。
编辑于2022-11-23 16:08:11 上海排序
 
基本概念
算法的稳定性
若待排序表中有两个关键字相同的元素Ri和Rj,若排序后两者顺序(相对位置)不变,则称该排序算法为稳定的,否则其是不稳定的
判断方法:有无远距离的数据交换
分类
内部排序
指在排序期间元素全部存放在内存中的排序
外部排序
指在排序期间元素无法全部同时存放在内存中,不惜在排序过程中不断在内、外存之间移动的排序
插入排序
基本思想
每次将一个待排序的记录按其关键字大小插入前面已排好序的子序列,直到全部记录插入完毕
直接插入排序
思路
从L[2]~L[n-1],每次将待排元素L[i]插入前面已经排好的序列,并将大于L[i]的元素顺位后移(边向前比较,边后移元素)
代码
空间效率
时间效率
最好:表中元素已经有序
比较次数:n-1
移动次数:0
最坏:逆序
比较次数:
移动次数:
平均
特性
稳定
适用于顺序存储和链式存储的线性表;为链式存储时,可以从前向后查找指定元素的位置(事实上,绝大多数内部排序算法只适用于顺序存储)
折半插入排序
思路
先折半找出元素的待插入位置,再统一移动待插入元素之后的所有元素
代码
时间效率
比较次数:(与表的初始状态无关)
移动次数:取决于排序表的初始状态
特性
稳定
仅适用于顺序表
希尔排序(缩小增量排序)
基本思想
将间隔为d1(步长/增量)的元素排成一组,将排序表分隔成若干子表,在每个子表内部分别进行直接插入排序,再缩小增量d2,重复上述过程,直至di=1为止
代码
空间效率:
时间效率:
特性
不稳定
仅适用于线性表为顺序存储的情况(因为利用了顺序存储的随机访问特性)
交换排序
基本思想
根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置
冒泡排序
思路
从后往前(或从前往后)两两比较相邻元素的值,若为逆序则交换之,直到序列比较完;每轮结果都将把最小元素交换到待排序列的首位(或将最大元素交换到待排序列的末位),如此循环n-1遍即可
代码
空间效率
时间效率
最好(第一趟排序没发生交换,直接跳出循环)
比较次数:n-1
移动次数:0
最坏(逆序)
比较次数
移动次数
特性
稳定
冒泡排序中产生的子序列一定是全局有序的(区别于直接插入),及其中所有元素一定大于或小于无序子序列中的所有元素,且每趟排序都会将一个元素放到其最终位置上
快速排序
思路
基于分治法,每次取某元素pivot作为基准,将序列划分为左右两个子表,再在子表内递归排序
代码
空间效率(递归栈)
时间效率
 
最坏(有序或逆序)
最好(对称,即每次基准都将序列等分)
特点
不稳定
内部排序算法中平均性能最优的算法
过程中不产生有序子序列,但每趟排序会把枢轴(基准)元素放到其最终位置上
外部排序
概念
当文件中的记录数较多,无法整个复制到内存中进行排序时;需每次将数据的一部分调入内存进行排序,排序过程中涉及多次内外存的交换
外部排序的方法
步骤
①对于k路归并排序,需要在内存中分配k个输入缓冲区和1个输出缓冲区
②对总共N个记录进行内部排序(使用某内部排序算法),生成r个内部有序的初始归并段(r=「N/L],L为内存中输入缓冲区个数)
③进行S趟k路归并,
1)把k个归并段的块读入到k个输入缓冲区
2)依次用”归并排序“算法从k个归并段中选出最小记录暂存到输出缓冲区(每次需比较k-1次)
3)当输出缓冲区满时,写出外存
4)若第i个输入缓冲区空,则从第i个归并段中读取下一个磁盘块
时间开销
读写外存的时间
与归并趟数S成正比
内部排序所需时间
内部归并所需时间
优化
1)增加归并路数k,仅需多路平衡归并
代价1:需增加相应的输入缓冲区
代价2:每次从k个归并段中选一个最小元素需(k-1)次关键字对比(可用败者树解决)
2)减少初始归并段数量r
多路平衡归并与败者树
基本思想
为使内部归并不受k的增大的影响,引入败者树,k个叶结点分别存放k个归并段在归并过程中当前参加比较的记录,内部用来记忆左右子树中的”失败者“,根结点指向最小数;
初始比较次数为k-1,此后每次选出一个最小值仅需「log2k]次的比较
比较次数
引入败者树后,比较次数与k无关;但随着k增大,也许增加输入缓冲区的个数,若总内存空间不变,则需减少每个缓冲区的容量,使内外存交换次数增大
置换-选择排序(生成初始归并段)
目的
增大每个归并段的长度(但不定长),从而减少归并段个数
步骤
设初始待排文件为FI,初始归并段输出文件为FO,内存工作区为WA(可容纳w个记录)
1)从FI输入w个记录到工作区WA。
2)从WA中选出其中关键字取最小值的记录,记为MINIMAX记录。
3)将MINIMAX记录输出到FO中去。
4)若FI不空,则从FI输入下一个记录到WA中。
5)从WA中所有关键字比MINIMAX记录的关键字大的记录中选出最小关键字记录,作为新的MINIMAX记录。
6)重复3)~5),直至在WA中选不出新的MINIMAX记录为止,由此得到一个初始归并段,输出一个归并段的结束标志到FO中去。
7)重复2)~6),直至WA为空。由此得到全部初始归并段。
最佳归并树
基本思想
1)每个初始归并段对应一个叶子结点,归并段所含块数即为叶子权值
2)归并树WPL=树中所有叶结点的带权路径长度之和
3)归并过程中的磁盘I/O次数=归并树的WPL*2
最佳归并树的构造方法
1)补充虚段
①k叉归并的最佳归并树必为严格k叉树,即树中只有度为k和0的结点
②若(初始归并段数-1)%(k-1)=0,说明刚好可以构成严格k叉树
③否则,需要补充若干个虚段(占0块的归并段)使得上式=0
2)构造k叉哈夫曼树
每次选择k个根结点权值最小的树合并,并将这k个根结点的权值之和作为新的根结点的权值
各种内部排序算法的比较及应用
内部排序算法的比较
内部排序算法的应用
①若n较小,可采用直接插入排序或简单选择排序。由于直接插入排序所需的记录移动次数较简单选择排序的多,因而当记录本身信息量较大时,用简单选择排序较好。
②若文件的初始状态己按关键字基本有序,则选用直接插入或冒泡排序为宜。
③若n较大,则应采用时间复杂度为O(nlogzn)的排序方法:快速排序、堆排序或归并排序。
1)快速排序被认为是目前基于比较的内部排序方法中最好的方法,当待排序的关键字随机分布时,快速排序的平均时间最短。
2)堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况,这两种排序都是不稳定的。
3)若要求排序稳定且时间复杂度为O(nlog2n),则可选用归并排序。
但本章介绍的从单个记录起进行两两归并的排序算法并不值得提倡,通常可以将它和直接插入排序结合在一起使用。先利用直接插入排序求得较长的有序子文件,然后两两归并。直接插入排序是稳定的,因此改进后的归并排序仍是稳定的。
④在基于比较的排序方法中,每次比较两个关键字的大小之后,仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程,由此可以证明:当文件的n个关键字随机分布时,任何借助于“比较”的排序算法,至少需要O(nlogzn)的时间。
⑤若n很大,记录的关键字位数较少且可以分解时,采用基数排序较好。
⑥当记录本身信息量较大时,为避免耗费大量时间移动记录,可用链表作为存储结构。
算法适用的存储结构
顺序存储结构适合随机存取和顺序存取,链式存储仅适合顺序存取
仅有顺序存取的算法可采用链式结构(如直接插入,冒泡),其余内部排序算法只能使用顺序存储
归并排序和基数排序
归并排序
 答:D 对大文件排序需使用外部排序,即将大文件分为若干小块,每次调入若干块进入内存进行排序,在内存进行排序时使用内部排序算法,最合适的是归并排序。
基本思想
2路归并排序将待排序表视为n个子表(每个子表长度为1),然后递归地两两归并,直到合成一个长度为n的有序表为止。
代码
性能分析
空间效率
时间效率
稳定
基数排序
基本思想
借助多关键字排序的思想处理单逻辑关键字
最高位优先(MSD)
按关键字位权重递减依次逐层划分成若干更小的子序列
最低位优先(LSD)
按关键字权重递增依次进行排序
排序过程(LSD)
基数r=10,需10个链队列;每个关键字为3位,需三趟”分配“和”收集“操作
性能分析
空间效率
时间效率
d趟分配和收集
一趟分配需要O(n)
一趟收集需要O(r)
与序列的初始状态无关
稳定
选择排序
基本思想
每一趟(i)在后面n-i+1个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,循环n-1趟
简单选择排序
思路
第i趟排序从L[i…n]中选择关键字最小的元素与L[i]交换,每一趟都可以确定一个元素的最终位置
代码
空间效率
时间效率
比较次数:n(n-1)/2
移动次数
最好:0
最坏:3(n-1)
特性
不稳定
堆排序
思路
堆
大根堆(大顶堆):结点值大于其左右孩子值
小根堆:结点值小于其左右孩子值
排序算法
①先将n个元素建成大根堆,堆顶元素即为最大值,输出之,并将堆底元素送入堆顶
②将堆顶元素向下调整,以维持大根堆性质,再输出堆顶元素,如此重复
排序过程
①对n个结点的完全二叉树,从最后一个结点的父结点(「n/2])开始筛选,交换父子结点使其称为大根堆(父亲结点可能继续下移至底部),在依次对以各结点(「n/2]~1)为根的子树进行筛选
②输出堆顶元素后,将最后一个堆顶元素与堆顶元素交换,再递归地将堆顶元素与孩子中的较大者交换次序
代码
大根堆建立算法
堆排序算法
插入操作
先将新结点放在堆的末端,再将其向上指向调整操作
时间复杂度
性能分析
空间效率
时间效率
建堆时间:
调整操作:
特性
不稳定
适用于顺序存储(因为有随机访问)