重要排序算法总结

Posted by Marlin on August 6, 2025

重要排序算法总结

一、排序算法的稳定性

定义
排序算法的稳定性是指:对于原始序列中两个相等的元素,在排序后它们的相对顺序不发生改变

  • 稳定:相等元素的相对位置在排序前后保持一致。
  • 不稳定:相等元素的相对位置可能被颠倒。

稳定性的重要性:

  • 对基础类型(如 int、double)无意义:因为值相同就无法区分,顺序无关紧要。
  • 对非基础类型(如对象、结构体)有意义:可保留多关键字排序中的前序结果,例如先按语文成绩排序,再按总分稳定排序。

二、主要排序算法对比总结

排序算法 时间复杂度(平均) 时间复杂度(最坏) 空间复杂度 是否稳定 备注
SelectionSort O(N²) O(N²) O(1) ❌ 不稳定 每次选最小值交换,会打乱相等元素顺序
BubbleSort O(N²) O(N²) O(1) ✅ 稳定 相邻比较,相等时不交换可保持稳定
InsertionSort O(N²) O(N²) O(1) ✅ 稳定 适合小规模或近有序数据
MergeSort O(N log N) O(N log N) O(N) ✅ 稳定 归并过程合并时控制顺序可保持稳定
QuickSort O(N log N) (期望) O(N²) O(log N) ❌ 不稳定 随机化快排应以期望时间复杂度为准,最坏情况概率极低
HeapSort O(N log N) O(N log N) O(1) ❌ 不稳定 堆调整过程会破坏相等元素顺序
CountSort O(N + K) O(N + K) O(K) ✅ 稳定 K 为数据范围,适用于整数且范围小
RadixSort O(N * D) O(N * D) O(K) ✅ 稳定 D 为位数,K 为辅助空间,常用于字符串或整数

⚠️ 注意

  • 随机快速排序的复杂度必须按照概率期望来评估,其期望时间复杂度为 O(N log N)。若仅看最坏情况 O(N²),则无法体现其实际高效性。
  • 计数排序(CountSort)和基数排序(RadixSort)是非比较排序,突破了 O(N log N) 的比较下界。

三、补充说明

1. 时间复杂度说明

  • O(N²):适用于小数据量或部分有序场景(如冒泡、插入、选择)。
  • O(N log N):通用高效排序,如归并、快排、堆排。
  • O(N + K) / O(N × D):线性时间排序,需满足特定条件(如整数、固定位数)。

2. 空间复杂度说明

  • O(1):原地排序,仅使用常数额外空间。
  • O(log N):快排递归栈深度(随机化下期望值)。
  • O(N):归并排序需要辅助数组。
  • O(K):计数排序需要大小为 K 的计数数组。

3. 实际应用建议

场景 推荐算法
通用排序,追求平均性能 随机快排(QuickSort)
要求稳定排序 归并排序(MergeSort)
小规模或近有序数据 插入排序(InsertionSort)
整数且范围较小 计数排序(CountSort)
多位数字或字符串排序 基数排序(RadixSort)
内存受限,不要求稳定 堆排序(HeapSort)

四、结语

掌握各排序算法的时间/空间复杂度稳定性是算法设计与工程实践的基础。在实际开发中,应根据数据特征(规模、类型、有序性、稳定性需求)选择合适的排序策略。

📚 提示:JDK 中 Arrays.sort() 对基本类型用双轴快排,对对象类型用稳定归并排序(Timsort 变种),正是综合考虑了性能与稳定性的体现。