【算法图解】排序算法大比拼:什么时候用哪个

冒泡/快排/归并/堆排/计数排序到底怎么选?本文用“稳定性、时间上界、空间、数据特征、工程约束”五个维度做对比,并给出面试可复述的选择逻辑。

18 分钟阅读
小明

【算法图解】排序算法大比拼:什么时候用哪个

排序算法你可能学过一堆:

  • 冒泡/选择/插入
  • 快排/归并/堆排
  • 计数/桶/基数

但一到工程/面试问“怎么选”,很多人就只会说:

快排平均快。

这不够。

真正的选择要看约束:

  • 你要不要稳定?
  • 你更怕最坏情况还是平均情况?
  • 内存紧不紧?
  • 数据有没有特殊结构(值域小、近似有序、重复多)?

这篇文章给你一个可复用的决策框架。


1. 先记住 5 个维度

  1. 稳定性:相等元素相对顺序是否保持
  2. 时间复杂度(平均/最坏):你能否接受退化
  3. 空间复杂度:能否开辅助空间
  4. 数据特征:是否近似有序、重复多、值域小
  5. 工程约束:语言内置实现、栈深度、安全性

2. 一张“面试可复述”的对比表

算法稳定平均时间最坏时间额外空间适用场景
冒泡$O(n^2)$$O(n^2)$$O(1)$教学/小数据/近似有序(带早停)
归并$O(n\log n)$$O(n\log n)$$O(n)$需要稳定 + 上界稳定
快排$O(n\log n)$$O(n^2)$$O(\log n)$平均快、内存友好(需防退化)
堆排$O(n\log n)$$O(n\log n)$$O(1)$要上界稳定 + 原地
计数✅(稳定实现)$O(n+k)$$O(n+k)$$O(k)$整数值域小、可接受空间

(注:快排空间一般指递归栈平均 $O(\log n)$。)


3. 你真正要掌握的是“选择逻辑”

3.1 先问:要稳定吗?

  • 要稳定:优先归并(或计数/基数在条件满足时)
  • 不要稳定:进入下一步

3.2 再问:能接受最坏 O(n²) 吗?

  • 不能:堆排 / 归并 / introsort(快排 + 退化保护)
  • 能:快排通常是默认首选

3.3 再问:内存紧吗?

  • 很紧:堆排、快排(原地)
  • 不紧:归并更稳(稳定 + 上界稳定)

3.4 最后看数据特征

  • 近似有序:插排(小规模)或 Timsort(许多语言内置)
  • 重复很多:三路快排(Dutch National Flag partition)
  • 值域很小:计数排序

4. 工程现实:你多半用的是内置排序

很多语言的内置排序不是“纯快排”。

常见策略:

  • 快排 + 退化保护(introsort)
  • 归并变体
  • Timsort(利用 runs,近似有序非常快)

面试里你可以顺带体现工程理解:

  • “我知道语言内置排序通常做了退化保护,不是教材里的朴素实现。”

5. 面试一问一答(可直接用)

  • 为什么快排平均快?
    • 因为分区后递归深度期望为 $\log n$,并且原地操作常数小。
  • 快排最坏为什么慢?怎么避免?
    • pivot 选择退化导致不平衡划分;用随机 pivot/三数取中/三路快排/退化切堆排。
  • 什么时候选堆排?
    • 需要 $O(n\log n)$ 上界稳定 + 原地内存。
  • 什么时候选计数?
    • 数据是整数且值域 $k$ 可控,愿意用 $O(k)$ 空间换时间。

总结

排序怎么选,不靠背算法名,靠约束:

  • 稳定性
  • 时间上界
  • 内存
  • 数据特征
  • 工程约束

如果你愿意,我可以再补一篇:三路快排(重复值多时的“快排救星”)。