8.6.各种内部排序算法的比较和应用
1. 比较排序算法
简单排序算法:
| 排序算法 | 最好时间复杂度 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 | 原地排序 |
|---|---|---|---|---|---|---|
| 冒泡排序 | \(O(n)\) | \(O(n^{2})\) | \(O(n^{2})\) | \(O(1)\) | 稳定 | 是 |
| 选择排序 | \(O(n^{2})\) | \(O(n^{2})\) | \(O(n^{2})\) | \(O(1)\) | 不稳定 | 是 |
| 插入排序 | \(O(n)\) | \(O(n^{2})\) | \(O(n^{2})\) | \(O(1)\) | 稳定 | 是 |
高效比较排序算法:
| 排序算法 | 最好时间复杂度 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 | 原地排序 |
|---|---|---|---|---|---|---|
| 希尔排序 | \(O(nlog_{2}n)\) | \(O(n^{1.3})\) | \(O(n^{2})\) | \(O(1)\) | 不稳定 | 是 |
| 快速排序 | \(O(nlog_{2}n)\) | \(O(nlog_{2}n)\) | \(O(n^{2})\) | \(O(log_{2}n)\) | 不稳定 | 是 |
| 归并排序 | \(O(nlog_{2}n)\) | \(O(nlog_{2}n)\) | \(O(nlog_{2}n)\) | \(O(n)\) | 稳定 | 否 |
| 堆排序 | \(O(nlog_{2}n)\) | \(O(nlog_{2}n)\) | \(O(nlog_{2}n)\) | \(O(1)\) | 稳定 | 否 |
2. 非比较排序算法
| 排序算法 | 最好时间复杂度 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 | 原地排序 |
|---|---|---|---|---|---|---|
| 计数排序 | \(O(n + k)\) | \(O(n + k)\) | \(O(n + k)\) | \(O(k)\) | 稳定 | 否 |
| 桶排序 | \(O(n + k)\) | \(O(n + k)\) | \(O(n^{2})\) | \(O(n + k)\) | 稳定 | 否 |
| 基数排序 | \(O(n * d)\) | \(O(n * d)\) | \(O(n * d)\) | \(O(n + k)\) | 稳定 | 否 |
符号说明:
n:数据规模
k:数据范围(计数排序)或桶的数量(桶排序)
d:数据的位数(基数排序)
拓展:
为什么快速排序比归并排序更常用。
快速排序的常数因子更小,且是原地排序,而归并排序需要\(O(n)\)的额外空间。
缓存友好,快速排序访问数据,缓存命中率高。
堆排序为什么不如快速排序快。
缓存不友好,堆的父子节点跳跃访问(非连续内存),导致缓存命中率低。
非自适应(不考虑已经排好序的元素的算法),无论数据是否有序,固定需要\(O(nlog_{n})\)的时间。
实现复杂,建堆和调整堆的算法比快排更难实现,

浙公网安备 33010602011771号