“小规模可以完全算清:$n=3$ 时 $\lceil\log 2 6\rceil=3$,故任何比较排序最坏至少 $3$ 次比较;插入排序恰以最坏 $3$ 次完成三元素排序,说明该下界在小规模处…”
形式陈述
归并排序实现比较排序:输入带可比较键的有限序列,输出包含相同元素重数的非降序列。本页采用自顶向下的稳定版本。长度
合并维护两段各自的首个未输出位置。两边都非空时,输出键较小的一项并推进该边;键相等时优先输出左段的项。一边耗尽后,把另一边剩余项依次接上。每次输出都移走一个未输出元素,因此合并会终止,输出中每条原记录恰好出现一次。
在单次比较、读取和搬移元素为常数成本的数组模型中,标准实现的运行时间满足递推关系
基例为
直觉
这是分治法中“先解决小问题,再组合答案”的典型例子。两边已经有序,所以全体剩余项中的最小者必在两个首项之一;不必重新搜索整段,也不必撤回已经输出的项。
把合并展开成层,每个内部层总共处理
例子与边界
合并为什么正确且稳定
排序
每次选择较小首项保持这三点。循环结束后,两侧已全部输出,于是结果有序且没有丢失重复记录。递归按更小长度终止,结合基例便证明整体排序正确。
若相等键附带身份,例如输入
表示和变体改变成本
链表可以通过重接节点合并,不需要线性大小的辅助元素数组;普通递归版本仍需调用栈。自底向上的链表归并可以进一步避免递归栈,但那是另一份执行方案,不能只从“用了链表”推出全部额外空间为常数。
标准数组版本需要线性辅助空间。更复杂的原地归并算法确实存在,不能反过来把它们的空间界安到本页方案上。自然归并排序会利用已经有序的连续段,某些输入因此更快;本页递推描述的是固定近半分割、逐层合并的版本。
Powersort先保留非降段与反转后的严格下降段,再按相邻原段中点的二进制分歧选择归并次序。对于段长比例pᵢ,归并体积距离最优有序树小于2n;该体积由记录参与归并的次数决定。galloping归并则改变一次双路归并内部的比较方式,用指数探测批量越过长前缀,两项改动分别影响调度与比较。
推论与应用
最坏
归并适合顺序扫描。外存排序在内存中缓冲多段并作多路归并,用更少轮次控制块传输;Funnel Sort再用递归缓冲结构取得缓存无关界。它们与本页共享合并思想,但需分别给出内存容量、块大小和 I/O 成本。
归并过程也能计数逆序对:当右首项严格小于左首项时,它还小于左段全部剩余项,因而一次加入左段剩余项数。相等时先取左边,避免把相等键误计为逆序。并行实现则还要选择并行合并方法,不能只把两个递归调用同时启动,就宣称所有合并成本也被平分。
参考资料
- Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022,§2.3:归并排序、正确性与递推分析。
- Donald E. Knuth, The Art of Computer Programming, Vol. 3: Sorting and Searching, 2nd ed., Addison-Wesley, 1998,§5.2.4:归并排序及其变体。