『基础』DS-8排序

知识点

[记录本章包含哪些内容]

未攻克

[记录还不会的知识点]

笔记

  • [>] 考纲内容
  • 排序基本概念
  • 插入排序:直接插入排序、折半插入排序、希尔排序
  • 变换排序:冒泡排序、快速排序
  • 选择排序:简单选择排序、堆排序
  • 二路归并排序
  • 基数排序
  • 外部排序
  • 排序算法的分析和应用
  • [>] 知识框架

  • [>] 复习要点

  • 堆排序、快速排序和归并排序为重难点
  • 各种排序算法思想、排序过程和特征(初态的影响、复杂度、稳定性、适用性)
  • 以选择题形式考察算法对比
  • 常用排序算法的代码熟练掌握
  • 看到某特定序列,知道最优排序算法

排序的定义

  • 重新排列元素种的元素,使表中元素满足按关键字有序的过程
  • 算法的稳定性:在使用某排序算法后,某元素所在位置与排序前一致,就说这个排序算法是稳定的,算法是否具有稳定性并不能衡量一个算法的好坏,主要是对算法性质进行描述。
  • 若待排序表种的关键字不允许重复,排序结果是唯一的,则对于排序算法的选择,稳定与否无关紧要
  • 排序算法分类
    • 分类依据:数据元素是否完全存放在内存中
    • 内部排序:排序期间元素完全存放在内存中的排序
    • 外部排序:排序期间元素无法全部同时存放在内存中,必须在排序过程中根据要求不断的在内、外存之间移动的排序
  • 排序算法分为:插入排序、交换排序、选择排序、归并排序和基数排序五大类
  • 内部排序算法的性能取决于算法的时间复杂度和空间复杂度,而时间复杂度一般是由比较和移动的次数决定的
  • 大多数的内部算法都更适用于顺序存储的线性表

小节选择题答案

序号1234
答案CABA
  • 拓扑排序是将有向图中所有结点排成一个线性序列,虽然也是在内存中进行的,但它不属于本章的内部排序范畴,且不满足本章的排序定义
  • 对任意序列进行比较的排序,求至少的比较次数应考虑最坏情况。对任意 n n n 个关键字排序的比较次数至少为 KaTeX parse error: Undefined control sequence: \ceil at position 1: \̲c̲e̲i̲l̲ ̲log_2(n!) 将 n=7 代入,得 13

第一类:插入排序

基本思想:每次将一个待排序的记录按其关键字大小插入前面已排好序的子序列,直到全部记录插入完成。

  • 三种算法:直接插入排序、折半插入排序和希尔排序

📖直接插入排序

  • 直接插入算法中,如果待插入的元素与有序序列中的某个元素相等,则将待插元素插入到相等元素的后面
  • 直接插入排序适用于顺序存储和链式存储的线性表,采用链式存储时无须移动元素
  • 直接插入排序的空间复杂度:仅使用了常数个辅助单元,因而空间复杂度为 O ( 1 ) O(1) O(1)
  • 行为:①从前面的有序子表中查找出待插入元素应该被插入的位置②给插入位置腾空间,将待插入元素复制到表中的插入位置。是边比较边移动元素,要求插入后的序列仍然保持按值有序

📖希尔排序

  • 直接插入排序算法更用于基本有序的排序表和数据量不大的排序表
  • 希尔排序是基于这两点分析对直接插入排序进行改进而得来的,又称缩小增量排序
  • 希尔排序仅适用于顺序存储的线性表
  • 基本思想:先将整个待排序的记录序列分割为若干个子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序
  • 算法步骤
  1. 选择一个增量序列 t 1 , t 2 , . . . , t k t_1,t_2,...,t_k t1,t2,...,tk ,其中 t 1 < t 2 , t k = 1 t_1<t_2,t_k=1 t1<t2,tk=1
  2. 按增量序列个数 k k k,对序列进行 k k k 趟排序(初始 k = l e n / 2 k=len/2 k=len/2
  3. 每趟排序,根据对应的增量 t i t_i ti,将待排序列分割成若干长度为 m m m 的子序列,分别对各子表进行直接插入排序,仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度

📖折半插入排序

  • 将比较和移动操作分离,即先折半查找出元素的插入位置,然后统一的移动待插入位置之后的所有元素
  • 折半插入排序适用于顺序存储的线性表
  • 折半插入排序与待排序表的初始状态无关

小节选择题答案

序号123456789101112
答案BABDCBCABCA
序号131415161718192021
答案BCACCBCBD

错题解析

错题序号汇总:4、12、18、19、20

  1. DA

  • 最坏情况:n-1+n-2+…+1 = n (n-1)/2
  • 最好情况:n-1
  • 比较次数最少大概率是在元素基本有序的情况下
  1. B


  1. D
  • 对同一待排序序列分别进行折半插入排序和直接插入排序,两者之间可能的不同之处是:元素间的比较次数
  • A 选项:排序的总趟数、B 选项:元素的移动次数、C 选项:使用辅助空间的数量都是一样的
  • D 选项:元素之间的比较次数,折半查找会比较快速的找到元素位置,而直接插入排序需要逐个比较元素才能确定待排序元素位置
  1. B

  • 间隔可能为:假如间隔为 2,就是 4 和 9 比,位置不对;同理,间隔为 4,就是 9 和 7 比,排序结果也不对,间隔为 5,是 8 和 9 比,结果不对
  1. A
  • 希尔排序的组内排序采用的是:直接插入排序

第二类:交换排序

交换:是指根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置

📖冒泡排序

基本思想:

  • 从后往前(或从前往后)两两比较相邻元素的值,若为逆序,则交换,直到序列比较完
  • 结果是将最小的元素交换到待排序列的第一个位置(或将最大的元素交换到待排序的最后一个位置)
  • 下一趟冒泡时,前一趟的最小元素不参与比较…,最多做 n-1 趟冒泡就能把所有元素排好序

性能分析:

  • 空间效率:仅使用常数个辅助单元,空间复杂度为 O ( 1 ) O(1) O(1)
  • 时间复杂度:
    • 最坏情况下:比较次数 n ( n − 1 ) / 2 n(n-1)/2 n(n1)/2 ,移动次数: [ 3 n ( n − 1 ) ] / 2 [3n(n-1)]/2 [3n(n1)]/2,时间复杂度: O ( n 2 ) O(n^2) O(n2)
    • 平均复杂度: O ( n 2 ) O(n^2) O(n2)
  • 适合顺序存储和链式存储的线性表

💡拓展:

双向冒泡排序是指对一个序列在正反两个方向交替进行扫描,第一趟把最大值放在序列的最右端,第二趟把最小值放在序列的最左端,之后在缩小的范围内进行同样的扫描,放在次右端、次左端,直到序列有序。

📖快速排序

快排基本思想是基于分治法:

  • 快速排序法使用分治法策略来把一个待排序列表分为两个子列表
  1. 从数列中挑出一个元素,称为“基准”(pivot)
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以放到任一边)。在这个分区退出后,该基准就处于数列的中间位置。这个称为分区(partition)操作
  3. 递归的把小于基准值元素的子数列和大于基准值元素的子数列排序
  • 一趟快速排序的过程是一个交替搜索和交换的过程
动图演示

性能分析:

  • 空间效率:由于快速排序是递归的,因此需要借助一个递归工作栈来保存每层递归调用的必要信息,其容量与递归调用的最大层数一致。

    • 最好情况下为 O ( l o g 2 n ) O(log_2n) O(log2n);
    • 最坏情况下:要进行 n − 1 n-1 n1 次递归调用,因此栈的深度为 O ( n ) O(n) O(n)
    • 平均情况下,栈的深度为 O ( l o g 2 n ) O(log_2n) O(log2n)
  • 时间效率:快排的运行时间与划分是否对称有关,快排的最坏情况发生在两个区域分别包含 n − 1 n-1 n1 个元素和 0 个元素时,这种最大限度的不对称性若发生在每层递归上,即对应于初始排序表基本有序或基本逆序时,就得到最坏情况下的时间复杂度 O ( n 2 ) O(n^2) O(n2)

  • 适用性:快速排序适合顺序存储的线性表

小节选择题答案

序号1234567891011
答案ACDBDDBCABDC
序号1213141516171819
答案CBCADAAXD

错题序号汇总:4、7、9、10、11、14、17、18

错题解析

  1. C

  1. A

  • B 、C、D 两趟之后头或尾的两个元素应该是有序的
  1. C

  2. AD

  • 越无序越快,越有序越慢

  • C 选项没有 A 选项均匀所以速度上要慢于 A 选项
  1. B
  • 移动次数越多:基准值,有一堆比基准值要大,有一堆比基准值要小,都需要移动
  1. C #Tips
  • 问题是问那个序列可能是执行了一趟排序后的序列
  • 执行了一趟排序后的序列最少最少能确定一个位置
  1. D
  • 问题:对固定元素个数后排序,问在最好情况下关键字的比较次数
  • 偶数个元素,划分不均匀,每个元素都需要比较一下,如:

17、18. **快速排序第二趟排序结果:2 趟最少可能确定 2 个或 3 个元素的位置

  • 写出最终元素的排序序列,确定哪个元素的位置找对了就说该元素位置被确定了

第三类:选择排序

选择排序的基本思想是:每一趟在后面 n − i + 1 n-i+1 ni+1 个待排序元素中选取关键字最小的元素,作为有序子序列的第 i i i 个元素,直到第 n − 1 n-1 n1 趟做完,待排序元素只剩下 1 个,就不用再选。

📖简单选择排序

基本思想:

  1. 假设排序表为 L,第 i i i 趟排序即从 L 中选择关键字最小的元素与 L ( i ) L(i) L(i) 交换
  2. 每一趟排序都可以确定一个元素的最终位置
  3. 经过 n − 1 n-1 n1 趟排序就可使整个排序表有序

性能分析:

  1. 空间效率:仅使用常数个辅助单元,空间效率为 O ( 1 ) O(1) O(1)
  2. 时间效率:元素移动次数不会超过 3 ( n − 1 ) 3(n-1) 3(n1) 次,最好情况是 0 次,元素间比较次数与序列初始状态无关,始终是 n ( n − 1 ) / 2 n(n-1)/2 n(n1)/2,,故时间复杂度始终是 O ( n 2 ) O(n^2) O(n2)
  3. 稳定性:不稳定
  4. 适用性:简单选择排序适合于顺序存储和链式存储的线性表,以及关键字较少的情况

📖堆排序 (重点)

参考链接:博客园

  1. 堆排序是指利用堆这种数据结构所设计的一种排序算法。
  2. 堆积一个近似完全二叉树的结构,并同时满足堆积的性质:
  • 子结点的键值或索引总是小于(或大于)它的父节点
  1. 堆排序是利用堆的概念的一种选择排序。分为:
  • 大顶堆:最大元素存放在根结点,且其任意一个非根结点的值小于或等于其双亲结点值,在堆排序中用于升序排列
  • 小顶堆:根结点是最小元素,每个结点的值都小于或等于其子结点,在堆排序中用于降序排列

示意图:(初始堆的构建)

输出堆顶元素后调整堆的比较次数的分析:

  • 将堆顶元素 87 输出,将最后一个元素与堆顶元素互换,向下进行筛选

  • 调整的时间和树高有关,为 O ( h ) O(h) O(h)。在建有 n n n 个元素的堆时,关键字的比较总次数不超过 4 n 4n 4n,时间复杂度为 O ( n ) O(n) O(n),说明可以在线性时间内将一个无序数组建成一个堆

堆的插入操作及比较次数的分析

  • 堆支持插入操作
  • 堆进行插入操作时,先将新结点放在堆末端,再对新结点向上执行调整操作

性能分析

  1. 空间效率:仅使用了常数个辅助单元,空间复杂度为 O ( 1 ) O(1) O(1)
  2. 时间效率:建堆时间为 O ( n ) O(n) O(n),之后有 n − 1 n-1 n1 次向下调整操作,每次调整的时间复杂度为 O ( h ) O(h) O(h),最好、最坏和平均情况下,堆排序的时间复杂度均为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
  3. 稳定性:不稳定
  4. 适用性:堆排序适用于顺序存储的线性表,适合关键字较多的情况

小节选择题答案

序号12345678910
答案ACDDBADADADD
序号11121314151617181920
答案CADDABCCCC

错题序号汇总:6、10、11、12、13、18、20

12、13 问比较次数:画图解答时,直接数交换次数,不需要想他需要进行比较才知道谁大谁小,可以快速得到正确答案。(做法来自 B 站 up 主"白话拆解数据结构")

**错题总结 **

  1. CC
  • 向具有 n n n 个结点的堆中插入一个新元素的时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n),删除一个元素的时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n),跟树的高度有关
  1. C

  • 做错的原因:先不把较小的放在顶部,在第二层时,明显可以看到有元素比 4 小,找出来后比较再决定哪个在顶(同层的都比完)

  1. D

  • 做错的原因:不可以直接把删除最小元素后的堆直接写出来,问的是堆,最终结果也要满足小根堆
  1. B

  • 问的是插入初始为空的大根堆,故不能将待排序列写成完全二叉树后再调整,得边插边调

第四、五类:归并排序和基数排序

归并排序

归并的含义是将两个或两个以上的有序表合并成一个新的有序表

  • 假定待排序表含有 n n n 个记录,则可视为 n n n 个有序的子表,每个子表的长度为 1,然后两两归并,得到 ⌈ n / 2 ⌉ \lceil n/2\rceil n/2 个长度为 2 或 1 的有序表
  • 继续两两归并… 重复,直到合成一个长度为 n n n 的有序表
  • 这种排序算法称为二路归并排序, n n n 个元素的二路归并排序需要进行 ⌈ l o g 2 n ⌉ \lceil log_2n \rceil log2n 趟,可延伸到 k k k 路排序,则需要进行 ⌈ l o g k n ⌉ \lceil log_kn \rceil logkn

性能分析:

  1. 空间效率:需要 n n n 个辅助单元,空间复杂度为 O ( n ) O(n) O(n)
  2. 时间效率:每趟归并的时间复杂度为 O ( n ) O(n) O(n),共需进行 ⌈ l o g 2 n ⌉ \lceil log_2n\rceil log2n 趟归并,时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
  3. 稳定性:稳定
  4. 适用性:归并排序适用于顺序存储和链式存储的线性表

基数排序

基数排序不基于比较和移动进行排序,而基于关键字各位的大小进行排序
基数排序是一种借助多关键字排序的思想对单逻辑关键字进行排序的方法

来自菜鸟教程

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数进行比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数

  • 利用了桶的概念,基数排序是根据键值的每位数字来分配桶

性能分析:

  1. 空间效率:一趟排序需要的辅助空间为 r r r r r r 个队列; r r r 个队头指针和 r r r 个队尾指针),但之后的排序中会重复使用这些队列,基数排序的空间复杂度为 O ( r ) O(r) O(r)
  2. 时间效率:基数排序需要进行 d 趟“分配”和“收集”操作。一趟分配需要遍历所有关键字,时间复杂度为 O ( n ) O(n) O(n),一趟收集需要合并 r r r 个队列,时间复杂度为 O ( r ) O(r) O(r)。基数排序的时间复杂度为 O ( d ( n + r ) ) O(d(n+r)) O(d(n+r))。与序列的初始状态无关
  3. 稳定性:稳定
  4. 适用性:基数排序适用于顺序存储和链式存储的线性表

扩展 1:计数排序

也是一种不基于比较的排序算法

计数排序思想:

  1. 对每个待排序元素 x x x,统计小于 x x x 的元素个数,利用该信息就可确定 x x x 的最终位置
  2. 如:若有 8 个元素小于 x x x,则 x x x 就排在第 9 号位置上
  3. 若有相同元素,该方案需做优化
  4. 算法设计上借助计数数组,将个数作为值放进去,然后遍历数组来排序

性能分析:

  1. 空间效率:是一种用空间换时间的做法。输出数组的长度为 n n n;辅助的计数数组的长度为 k k k,空间复杂度为 O ( n + k ) O(n+k) O(n+k)。若不把输出数组视为辅助空间,则空间复杂度为 O ( k ) O(k) O(k)
  2. 时间效率:当 k = O ( n ) k=O(n) k=O(n) 时,计数排序的时间复杂度为 O ( n ) O(n) O(n),当 k > O ( n l o g n ) k>O(nlogn) k>O(nlogn) 时,效率不如一些基于比较的排序(如:快排、堆排序)
  3. 稳定性:稳定
  4. 适用性:计数排序适合顺序存储的线性表。计数排序适用于序列中的元素是整数且元素范围(0~k-1)不能太大,否则会造成辅助空间的浪费

扩展 2:桶排序 (不在大纲内,属于拓展内容)

堆排序是计数排序的升级版。利用了函数的映射关系,高效与否的关键在于这个映射函数的确定。对桶中元素的排序,选择哪种比较排序算法对于性能的影响很重要。

为了使桶排序更高效,需做到:

  • 在额外空间充足的情况下,尽量增大桶的数量
  • 使用的映射函数能够将输入的 n n n 个数据均匀的分配到 k k k 个桶内

什么时候最快: 当输入的数据可以均匀的分配到每一个桶中
什么时候最慢: 当输入的数据被分配到了同一个桶中


  • 基数排序:根据键值的每位数字来分配桶
  • 计数排序:每个桶只存储单一数值
  • 桶排序:每个桶存储一定范围的数值

小节选择题答案

序号12345678910111213
答案CCDCBBDABDCBC
序号141516171819
答案CDACBA

错题序号汇总:3、4、6、7、8、11、12、13、16、18

💡空间复杂度
最好最坏平均
冒泡排序 O ( 1 ) O(1) O(1) O ( 1 ) O(1) O(1) O ( 1 ) O(1) O(1)
快速排序 O ( l o g 2 n ) O(log_2n) O(log2n) O ( n ) O(n) O(n) O ( l o g 2 n ) O(log_2n) O(log2n)
简单选择排序 O ( 1 ) O(1) O(1) O ( 1 ) O(1) O(1) O ( 1 ) O(1) O(1)
堆排序 O ( 1 ) O(1) O(1) O ( 1 ) O(1) O(1) O ( 1 ) O(1) O(1)
归并排序 O ( n ) O(n) O(n) O ( n ) O(n) O(n) O ( n ) O(n) O(n)
基数排序 O ( r ) O(r) O(r),r 为辅助空间队列
插入排序 O ( 1 ) O(1) O(1) O ( 1 ) O(1) O(1) O ( 1 ) O(1) O(1)

错题解析

  1. A
  • 排序算法中,排序过程中比较次数的数量级与序列初始状态无关的是:归并排序、简单选择排序
  • 排序算法中,排序过程中移动次数与关键字的初始状态无关的是:基数排序、简单选择排序
  1. B

  1. A
  • 将两个各有 N 个元素的有序表合并成一个有序表,最少的比较次数是 N,最多的比较次数是 2N-1
  1. C

  1. D

  • 先排权重小的个位,也就是 k 2 k_2 k2
  • 简单选择排序和直接插入排序区别:简单选择排序是不稳定的排序,直接插入排序才不会影响后面元素的排序, k 1 k_1 k1 要稳定
  1. C

  • 第一趟按照个位数分别把数放到对应的桶上,一个桶上多个元素,出的时候是从下至上出,入的时候也是从底下往上放
  • 第二趟是按照十位,从元素最后–>最前管
  • 以上是按照最低位优先(LSD)
  1. D

  • 十进制就放 10 个

内部排序算法的比较和应用

  • 归并排序、快速排序基于分治的思想

  • 排序算法中,排序过程中比较次数的数量级与序列初始状态无关的是:归并排序、简单选择排序

  • 排序算法中,排序过程中移动次数与关键字的初始状态无关的是:基数排序、简单选择排序

  • 平均复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) 的稳定排序算法只有归并排序

  • 折半插入排序、希尔排序、快速排序和堆排序适用于顺序存储

  • 直接插入排序、冒泡排序、简单选择排序、归并排序和基数排序既适用于顺序存储、又适用于链式存储

  • 冒泡排序、简单选择排序和堆排序在每趟处理后都能产生当前的最大值或最小值

  • 快速排序一趟处理至少能确定一个元素的最终位置

  • [>] 内部排序算法的应用

  • 选取排序算法需要考虑的因素:

  1. 待排序的元素个数 n n n
  2. 待排序的元素的初始状态
  3. 关键字的结构及其分布情况
  4. 稳定性的要求
  5. 存储结构及辅助空间的大小限制等
  • 排序算法小结:
  1. n n n 较小,可采用直接插入排序或简单选择排序。由于直接插入排序所需的记录移动次数比简单选择排序的多,因此当记录本身信息量较大时,用简单选择排序比较好
  2. n n n 较大:应采用时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) 的排序算法:快速排序、堆排序或归并排序。当待排序的关键字随机分布时,快速排序被认为是目前基于比较的内部排序算法中最好的算法/。堆排序所需的辅助空间少于快速排序,且不会出现快速排序可能的最坏情况,这两种排序都是不稳定的。若要求稳定且时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n),可选择归并排序
  3. 若待排序列的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜
  4. 在基于比较的排序算法中,每次比较两个关键字的大小之后,仅出现两种可能的转移,因此可用一颗二叉树来描述比较判定过程,由此可以证明:当文件的 n n n 个关键字随机分布时,任何借助于“比较”的排序算法,至少需要 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) 的时间
  5. n n n 很大,记录的关键字位数较少且可以分解时,采用基数排序较好
  6. 当记录本身信息量较大时,为避免耗费大量时间移动记录,可用链表作为存储结构

小节选择题答案

序号1234567891011
答案ABDBBDADCC
序号12131415161718192021
答案CBAABCDDDC
    1. 稳定排序的有:冒泡排序、直接插入排序、归并排序
      平均时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) 的有:希尔排序、快速排序、堆排序、归并排序
      在最好情况下,时间复杂度可以达到线性时间的有:冒泡排序、直接插入排序

错题序号汇总:2、5、7、9、11、12、17、19

错题解析

  • 就排序算法所用的辅助空间而言,堆排序 O ( 1 ) O(1) O(1) <快速排序 O ( l o g 2 n ) O(log_2n) O(log2n) <归并排序 O ( n ) O(n) O(n)
  • 对 n 个元素排序,排序趟数肯定为 n − 1 n-1 n1 趟的排序算法是:简单选择排序和直接插入排序
  • 一般情况下,查找效率最低的数据结构是堆
  • 对于同等大小的不同初始序列,总比较次数一定的是折半插入排序和简单选择排序
  • 一台计算机具有多核 CPU,可以同时执行相互独立的任务。归并排序的各个归并段可以并行执行,在下列排序算法中,不可以并行执行的有基数排序、冒泡排序
  • 若将顺序存储更换为链式存储,则算法的时间效率会降低的是希尔排序和堆排序
  • 对大部分元素已经有序的数组排序时,直接插入排序比简单选择排序效率更高,其原因是:直接插入排序过程中元素之间的比较次数更少

外部排序

#todo暂未理解 考虑学完组成原理之后回看

参考链接


数据结构第一轮复习至此结束:20240614

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值