408答疑
五、归并排序、基数排序和计数排序
归并排序
概述
归并排序与交换、选择等排序的思想不一样,归并的含义是将两个或两个以上的有序表合并成一个新的有序表。假定待排序表含有 n n n 个记录,则可将其视为 n n n 个有序的子表,每个子表的长度为 1,然后两两归并,得到 ⌈ n / 2 ⌉ \lceil n/2 \rceil ⌈n/2⌉ 个长度为 2 或 1 的有序表;继续两两归并……如此重复,直到合并成一个长度为 n n n 的有序表为止,这种排序算法称为二路归并排序。
如下图所示为二路归并排序的一个例子,经过三趟归并后合并成了有序序列。
归并排序思想的应用
- Merge() 的功能是将前后相邻的两个有序表归并为一个有序表。设两段有序表 A[low…mid]、A[mid+1…high] 存放在同一顺序表中的相邻位置,先将它们复制到辅助数组 B 中。每次从 B 的两段中取出一个记录进行关键字的比较,将较小者放入 A 中,当 B 中有一段的下标超出其对应的表长(即该段的所有元素都已复制到 A 中)时,将另一段的剩余部分直接复制到 A 中。
- 一趟归并排序的操作是,调用 ⌈ n / 2 h ⌉ \lceil n/2h \rceil ⌈n/2h⌉ 次算法 Merge(),将 L[1…n] 中前后相邻且长度为 h h h 的有序段进行两两归并,得到前后相邻、长度为 2 h 2h 2h 的有序段,整个归并排序需要进行 ⌈ log 2 n ⌉ \lceil \log_2 n \rceil ⌈log2n⌉ 趟。
递归形式的二路归并排序算法是基于分治的,其过程如下:
- 分解:将含有 n n n 个元素的待排序表分成各含 n / 2 n/2 n/2 个元素的子表,采用二路归并排序算法对两个子表递归地进行排序。
- 合并:合并两个已排序的子表得到排序结果。
性能分析
- 空间效率:Merge() 操作中,辅助空间刚好为 n n n 个单元,因此算法的空间复杂度为 O ( n ) O(n) O(n)。
- 时间效率:每趟归并的时间复杂度为 O ( n ) O(n) O(n),共需进行 ⌈ log 2 n ⌉ \lceil \log_2 n \rceil ⌈log2n⌉ 趟归并,因此算法的时间复杂度为 O ( n log 2 n ) O(n \log_2 n) O(nlog2n)。
- 稳定性:由于 Merge() 操作不会改变相同关键字记录的相对次序,因此二路归并排序算法是一种稳定的排序算法。
- 适用性:归并排序适用于顺序存储和链式存储的线性表。
注意事项
- 一般而言,对于 N N N 个元素进行 k k k 路归并排序时,排序的趟数 m m m 满足 k m = N k^m = N km=N,从而 m = log k N m = \log_k N m=logkN,又考虑到 m m m 为整数,因此 m = ⌈ log k N ⌉ m = \lceil \log_k N \rceil m=⌈logkN⌉。这和前面的二路归并排序算法是一致的。
九、参考资料
鲍鱼科技课件
b站免费王道课后题讲解:
网课全程班: