算法-比较排序
本系列可作为算法学习系列的笔记,小编会将代码记录下来,大家复制下来就可以练习了,方便大家学习。小编作为新晋码农一枚,会定期整理一些写的比较好的代码,作为自己的学习笔记,会试着做一下批注和补充,如转载或者参考他人文献会标明出处,非商用,如有侵权会删改!欢迎大家斧正和讨论!
系列文章目录
计算矩阵的鞍点个数
算法-比较排序
目录
系列文章目录
一、比较排序算法概述
1. 梳排序(Comb Sort)
2. 堆排序(Heap Sort)
3. 归并排序(Merge Sort)
4. 快速排序(Quick Sort)
5. 内省排序(Introsort)
6. Timsort
总结对比
总结
一、比较排序算法概述
比较排序是指通过比较元素大小来决定排序顺序的算法,大多数排序算法都属于比较算法。在比较排序中,待排序对象可以是任意数据类型。其时间复杂度下界为 O(n log n)。常见的比较排序算法包括:梳排序、堆排序、归并排序、快速排序、内省排序和Timsort。
这里为什么比较排序的时间复杂度下界为O(n log n), 详见小编的另一个笔记链接:
为什么比较排序算法的时间复杂度下界是 Ω(n log n)?-CSDN博客
1. 梳排序(Comb Sort)
算法思想: 改进的冒泡排序,通过较大的间隔(gap)逐步缩小来减少逆序对。
时间复杂度:
- 平均 O(n²),但优化后可达 O(n log n)(使用Shrink Factor ≈1.3)。
稳定性: 不稳定。
练习题目:
输入数组: [8, 4, 1, 3, 2, 7, 6, 5]
排序过程:
- 初始 gap = 8 / 1.3 ≈ 6 → 比较
[8,6]
→ 交换 →[6,4,1,3,2,7,8,5]
- gap = 6 / 1.3 ≈ 4 → 比较
6-2,4-7,1-8,3-5
→ 交换1-8
→[6,4,5,3,2,7,1,8]
- gap = 4 / 1.3 ≈ 3 → 比较
6-3,4-2,5-7
→ 交换6-3,4-2
→[3,2,5,6,4,7,1,8]
- gap = 3 / 1.3 ≈ 2 → 比较
3-5,2-6,5-4,6-7,4-1,7-8
→ 交换5-4,4-1
→[3,2,4,6,1,7,5,8]
- gap = 2 / 1.3 ≈ 1 → 进行冒泡排序 → 最终
[1,2,3,4,5,6,7,8]
结果: [1, 2, 3, 4, 5, 6, 7, 8]
2. 堆排序(Heap Sort)
算法思想: 利用最大堆(或最小堆)结构,每次取出堆顶元素并调整堆。
时间复杂度:
- 建堆 O(n),每次调整 O(log n) → 总体 O(n log n)。
稳定性: 不稳定。
练习题目:
输入数组: [8, 4, 1, 3, 2, 7, 6, 5]
排序过程:
- 建堆(最大堆):
[8,5,7,4,2,1,6,3]
- 交换
8
(堆顶)和3
(末尾),调整堆 →[7,5,6,4,2,1,3|8]
- 交换
7
和3
→[6,5,3,4,2,1|7,8]
- 重复操作 → 最终
[1,2,3,4,5,6,7,8]
结果: [1, 2, 3, 4, 5, 6, 7, 8]
3. 归并排序(Merge Sort)
算法思想: 分治法,递归拆分数组,再合并有序子数组。
时间复杂度: O(n log n)(最坏、平均、最优)。
稳定性: 稳定。
练习题目:
输入数组: [8, 4, 1, 3, 2, 7, 6, 5]
排序过程:
- 拆分:
[8,4,1,3]
和[2,7,6,5]
- 递归拆分 →
[8,4]
[1,3]
[2,7]
[6,5]
- 合并:
[4,8]
[1,3]
[2,7]
[5,6]
- 继续合并 →
[1,3,4,8]
和[2,5,6,7]
- 最终合并 →
[1,2,3,4,5,6,7,8]
结果: [1, 2, 3, 4, 5, 6, 7, 8]
4. 快速排序(Quick Sort)
算法思想: 分治法,选取基准(pivot),划分左右子数组递归排序。
时间复杂度:
- 平均 O(n log n),最坏 O(n²)(如已排序数组)。
稳定性: 不稳定。
练习题目:
输入数组: [8, 4, 1, 3, 2, 7, 6, 5]
排序过程(取第一个元素为pivot):
- pivot=8 → 划分
[4,1,3,2,7,6,5]
+[]
- pivot=4 →
[1,3,2]
+[7,6,5]
- pivot=1 →
[]
+[3,2]
- pivot=3 →
[2]
+[]
- 合并 →
[1,2,3,4,5,6,7,8]
结果: [1, 2, 3, 4, 5, 6, 7, 8]
5. 内省排序(Introsort)
算法思想: 结合快速排序、堆排序和插入排序,避免快速排序的最坏情况。
时间复杂度: O(n log n)(最坏情况由堆排序保证)。
稳定性: 不稳定。
练习题目:
输入数组: [8, 4, 1, 3, 2, 7, 6, 5]
排序过程:
- 快速排序递归到一定深度(如
log n
)→ 改用堆排序 - 最终结果与堆排序相同
结果: [1, 2, 3, 4, 5, 6, 7, 8]
6. Timsort
算法思想: 归并排序 + 插入排序优化,适用于现实数据(部分有序)。
时间复杂度: O(n log n)(最坏),对部分有序数据接近 O(n)。
稳定性: 稳定。
练习题目:
输入数组: [8, 4, 1, 3, 2, 7, 6, 5]
排序过程:
- 分块(run):
[8]
[4]
[1,3]
[2,7]
[6]
[5]
- 插入排序优化小run →
[1,3]
[2,7]
- 归并合并 →
[1,2,3,7]
+[4,5,6,8]
- 最终合并 →
[1,2,3,4,5,6,7,8]
结果: [1, 2, 3, 4, 5, 6, 7, 8]
总结对比
算法 | 平均时间复杂度 | 最坏时间复杂度 | 稳定性 | 适用场景 |
---|---|---|---|---|
梳排序 | O(n²) | O(n²) | 不稳定 | 改进冒泡排序 |
堆排序 | O(n log n) | O(n log n) | 不稳定 | 内存受限场景 |
归并排序 | O(n log n) | O(n log n) | 稳定 | 大数据量、外部排序 |
快速排序 | O(n log n) | O(n²) | 不稳定 | 通用高效排序 |
内省排序 | O(n log n) | O(n log n) | 不稳定 | 避免快排退化 |
Timsort | O(n log n) | O(n log n) | 稳定 | 实际数据(如Python、Java) |
练习题目结果均为: [1, 2, 3, 4, 5, 6, 7, 8]
总结
本文介绍了6种常见比较排序算法:梳排序(改进冒泡排序,平均O(n²))、堆排序(利用堆结构,O(nlogn))、归并排序(分治合并,稳定O(nlogn))、快速排序(基于pivot划分,平均O(nlogn))、内省排序(结合快排和堆排)以及Timsort(归并+插入优化,适合现实数据)。通过示例数组[8,4,1,3,2,7,6,5]演示各算法执行过程,最终均输出有序结果[1,2,3,4,5,6,7,8]。文章对比了各算法的时间复杂度、稳定性和适用场景,可作为算法学习参考笔记。