Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

比较排序的下限(进阶)

复习

  • 计数排序与基数排序:不靠比较的排序
  • 归并排序与快速排序:O(n log n)
  • 大 O 记号:描述增长量级

本章为进阶内容,零基础读者可以跳过,不影响后续阅读。

TL;DR

  • 只靠两两比较的排序,至少要 Ω(n log n) 次比较
  • 这个下界来自“决策树”的论证
  • 它说明 O(n log n) 已经是最优的一类
  • 计数排序等更快,是因为它们不靠比较

正文

  归并、快排、堆排,都能做到 O(n log n)。为什么没有更快的比较排序?这一章给出一个很漂亮的回答:因为它们不可能更快。

把所有选择画成一棵树

  只靠比较的排序,本质上是在做一连串判断:“A 比 B 大吗?”每次比较只有两种结果,于是整个决策过程可以画成一棵二叉树——每个节点是一次比较,两条分支对应两种结果。

  在这棵树里,从根走到某个叶子,就代表了一次完整的判断过程,而叶子对应一种最终的排列顺序。

  关键来了:

  • n 个元素,一共有 n! 种可能的排列
  • 要想区分所有情况,决策树至少要有 n! 个叶子
  • 一棵高度为 h 的二叉树,最多只有 个叶子

于是有了下界

  要装下 n! 个叶子,树的高度 h 必须满足 2ʰ ≥ n!,也就是 h ≥ log₂(n!)

  利用一个近似,log₂(n!) 约等于 n log n 的量级。所以:

任何只靠比较的排序,最坏情况下至少要 Ω(n log n) 次比较。

  这说明归并、快排、堆排已经摸到了比较排序的理论天花板——不可能有渐近更快的比较排序了。

那线性排序怎么来的

  你可能会问:前面计数排序明明是线性的,不就和这个下界矛盾了吗?

  不矛盾。因为下界只适用于**“只靠比较”的排序。计数排序、基数排序绕开了比较,转而利用数据的取值范围、位数**这些额外信息。它们打破了比较排序的天花板,靠的是对数据提出更多的先决条件。

  这又是一次熟悉的启示:定理给出的限制,往往也指明了突破的方向——换一种前提,就能走出另一条路。

思考题 1

  为什么只靠比较的排序,无法普遍快过 O(n log n)

思考题 2

  计数排序能达到线性级别,这与比较排序的下界矛盾吗?

小结

知识点

  • 比较排序可建模为决策树
  • n 个元素有 n! 种排列,树高至少 log₂(n!)
  • 因此比较排序下界为 Ω(n log n)
  • 非比较排序靠额外前提突破这一下界

参考资料

  1. Wikipedia(zh):比较排序:仅依靠比较的排序算法及其下界
  2. Wikipedia(zh):大O符号:描述算法复杂度的记号

思考题答案(仅供参考)

思考题 1

  因为只靠比较的排序每一步只有两个结果,整个过程对应一棵二叉树。要区分 n! 种排列,树高至少要 log₂(n!),约为 n log n 量级。因此不存在渐近更快的比较排序。

思考题 2

  不矛盾。这个下界只约束“只靠比较”的排序。计数排序不进行比较,而是利用数据的取值范围直接统计位置,因此不受该下界限制。它更快,是以对数据提出额外要求为代价的。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪