引言
- 思维导图中,标红的是重点内容,标黄的是次重点。
- 码字不易,如果这篇文章对您有帮助的话,希望您能点赞、收藏、加关注!您的鼓励就是我前进的动力!
知识点思维导图
补充:
- 排序定义:使得序列成为按关键字有序的序列的操作。
- 稳定性:对于关键字相等的几个元素,若排序前和排序后的顺序不变,则所用的排序方法是稳定的;反之,则不稳定。
- 影响排序算法的三个因素:
1)时间性能:尽可能少进行关键字比较和记录移动;
2)辅助空间:指执行算法所需要的其他存储空间;
3)算法的复杂性:指算法本身的复杂度。 - 内部排序:待排序的记录放在计算机内存中进行排序,整个排序过程不需要访问外存便能完成排序。
- 外部排序:排序的记录数量比较大,排序期间文件的全部记录不能同时存放在计算机的内存里,排序过程中需要不断地进行内存和外存之间的数据交换。
注意事项与易错点
(NULL)
题型与算法
一、插入排序
(一)直接插入排序
- 基本思想:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增一的有序表。
- 具体操作步骤:
1)将当前记录与前一个记录比较;
2)比前一位大(按升序排),则符合顺序,不动;
3)比前一位小,则把当前位插入到前面的合适位置。方法:先将当前数据赋值给 r [ 0 ] r[0] r[0],再将前面的数一个一个与 r [ 0 ] r[0] r[0]比较,比 r [ 0 ] r[0] r[0]大就往前移一位,直到某个数小于或等于 r [ 0 ] r[0] r[0],说明位置合适,此数不再前移,并把 r [ 0 ] r[0] r[0]的数值放到当前位置。 - 时间复杂度:最好情况为
O
(
n
)
O(n)
O(n),最坏情况为
O
(
n
2
)
O(n^2)
O(n2)。平均时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:辅助空间只有R[0],S(n)=O(1)
稳定性:稳定
(二)折半插入排序
- 基本思想:在有序表中折半查找,并在适当位置插入,把原来位置上的元素向后顺移,即折半插入排序。
- 优点:比较的次数减少,全部元素比较次数仅为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
- 时间效率:虽然比较次数减少,但移动次数并未减少,所以排序效率仍为
O
(
n
2
)
O(n^2)
O(n2) 。
空间效率: O(1)
稳定性:稳定 - 注意:链表可以直接插入,但是无法“折半查找”!
(三)希尔排序
- 基本思想:将整个待排序的记录序列分割为若干个子序列并分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。
- 基本步骤:
1)待排序的记录按照距离d(增量)分成若干个组,把所有下标值相差d倍数的记录放在一组,在各组内进行直接插入排序。
2)然后改变d的值,使其逐步缩小,各组的记录随着d的变小而趋向有序。因而重新分组后,排序速度较快。当增量减小到1时,已达到基本有序,最后再进行直接插入排序。 - 时间复杂度:
O
(
n
l
o
g
2
n
)
O(nlog_2n)
O(nlog2n)。
空间复杂度:空间复杂度为 O ( 1 ) O(1) O(1)。
稳定性:不稳定。
二、快速排序
(一)冒泡排序
- 基本思想:两两比较相邻的关键字,如果反序则交换,直到没有反序记录为止。
- 时间复杂度为:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度: O ( 1 ) O(1) O(1)
稳定性:稳定
(二)快速排序
- 基本思想:首先选取一个记录(第一个)作为界点,然后将所有关键字较它小的记录都安置在它的位置之前,较它大的记录都安置在它的位置之后。由此以该“界点”记录最后所落的位置为分界线,将整个序列分割成两个子序列。
然后分别对这两个子序列重复施行上述方法,直到所有的对象都排在相应位置上为止。 - 实现步骤:
1)附设两个指针low和high,其初值分别指向数组的单元1和单元n。
2)选择第一个记录为界点,其关键字为pivotkey。将pivotkey复制到 r [ 0 ] r[0] r[0]中,从high所指的位置起向前搜索找到第一个关键字小于pivotkey的记录复制到low所指位置中。(high向前找小的)
3)然后从low所指位置起向后搜索,找到第一个关键字大于pivotkey的记录复制到high所指位置中。(low向后找大的)
4)重复上两步直到low=high为止。 - 时间复杂度:快速排序平均计算时间是
O
(
n
l
o
g
2
n
)
O(nlog_2n)
O(nlog2n)。平均计算时间而言,快速排序是内部排序中最好的。在最坏的情况,其时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:快速排序是递归的,最大递归调用层次数与递归树的高度一致,理想情况为 ┏ l o g 2 ( n + 1 ) log_2(n+1) log2(n+1)┓。因此,要求存储开销为 O ( l o g 2 n ) O(log_2n) O(log2n)
稳定性:不稳定
三、选择排序
(一)简单选择排序
- 基本思想:每一趟从待排的无序区中选出关键字最小的记录,顺序放在已排好序的子序列的最后,直至记录全部排完。
- 时间复杂度为:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度: O ( 1 ) O(1) O(1)
稳定性:不稳定
(二)堆排序
- 基本思想:堆排序(HeapSort)是对选择排序的一种改进方法,属于树形排序法。在排序过程中,将R[1…n]看成是一棵完全二叉树的顺序存储结构,利用双亲结点和孩子结点间的内在关系来选择关键字最小的记录。
- 堆的概念:设有n个元素的序列 k1,k2,…,kn,当且仅当满足 K i ≤ K 2 i K_i≤K_{2i} Ki≤K2i, K i ≤ K 2 i + 1 K_i≤K_{2i+1} Ki≤K2i+1或 K i ≥ K 2 i K_i≥K_{2i} Ki≥K2i, K i ≥ K 2 i + 1 K_i≥K_{2i+1} Ki≥K2i+1时,称之为堆。其中,K1必是数列中的最大值或最小值,可分别成为大根堆和小根堆。
- 排序过程:
1)以初始关键字序列,建立堆(就是一个反复筛选的过程);
2)输出堆顶元素;
3)调整余下的元素,使其成为一个新堆;
4)重复第2,3步n次,得到一个有序序列。 - 输出堆顶后,余下元素的调整方法(筛选法):
1)将堆底推向堆顶,成为新结点,然后将新结点的和其左右孩子进行比较。
2)若新堆顶最小(或最大),则无须调整。
3)若新结点的左孩子最小,则将堆顶与左孩子交换位置。这样若导致左孩子的子树不再是堆,就对左孩子的子树也进行上述比较交换。一直调整到树叶,即构建好了新的堆。
4)右孩子最小(或最大)同理。 - 时间复杂度:最坏情况下
T
(
n
)
=
O
(
n
l
o
g
2
n
)
T(n)=O(nlog_2n)
T(n)=O(nlog2n)
空间复杂度: S ( n ) = O ( 1 ) S(n)=O(1) S(n)=O(1)
稳定性:不稳定
四、归并排序
- 所谓归并就是将两个或两个以上的有序表合并成一个有序表。
- 基本思想:将记录序列R[1…n]看成是n个长度为1的子序列,然后两两归并,得到┏n/2┓个长度为2或1的有序子序列。两两归并,重复此过程,直至得到一个长度为n的有序序列为止。每次都将两个序列合并成一个序列,称为2路归并排序。
- 算法相当于是在重复线性表的合并操作。
- 时间复杂度:
T
(
n
)
=
O
(
n
l
o
g
2
n
)
T(n)=O(nlog_2n)
T(n)=O(nlog2n)
空间复杂度: S ( n ) = O ( n ) S(n)=O(n) S(n)=O(n)
稳定性:稳定
五、基数排序
- 采用“分配”与“收集”的办法,利用对多关键字进行排序的思想实现对单关键字进行排序的方法。
六、各种内部排序方法比较
- 按平均时间排序方法分为四类
O ( n 2 ) O(n^2) O(n2)、 O ( n l o g n ) O(nlogn) O(nlogn)、 O ( n 1 + ε ) O(n^{1+ε}) O(n1+ε)
快速排序是基于比较的内部排序中平均性能最好的。 - 可以使用链表作为存储结构:直接插入排序、归并排序。
- 不宜使用链表作为存储结构:折半插入排序、希尔排序、快速排序、堆排序。
- n较大时:分布随机,稳定性不做要求,则采用快速排序;内存允许,要求排序稳定时,则采用归并排序。
- n较小时:基本有序,要求稳定,则采用直接插入排序;分布随机,稳定性不做要求,则采用简单选择排序。
- 比较图:
方法心得
(NULL)
参考资料:
[1] 程杰. 大话数据结构. 北京:清华大学出版社, 2020.
[2]严蔚敏,吴伟民. 数据结构 (C语言版). 北京:清华大学出版社, 1997.