📘 快速排序(Quick Sort)
1. 问题定义
给定数组 (A[1...n]),目标是将其重排为:
A\[1\]≤A\[2\]≤⋯≤A\[n\]\]\[A\[1\] \\le A\[2\] \\le \\dots \\le A\[n\]\]\[A\[1\]≤A\[2\]≤⋯≤A\[n\]
2. 核心思想
快速排序基于:
🔹 分治(Divide and Conquer)
将问题递归拆解为两个子问题。
在本算法中具体体现为:
- 选择一个元素作为枢轴(pivot)
- 执行划分(partition)
- 对左右子数组递归排序
3. 核心术语(精确定义 + 可理解解释)
🔸 3.1 枢轴(Pivot)
定义:
用于划分数组的参考元素
作用:
将数组分为两部分:
\\text{左区间} \\le pivot \\le \\text{右区间}
理解:
pivot 是"分界值",它最终会被放到正确位置
🔸 3.2 划分(Partition)
定义:
对区间 (A[l...r]) 重排,使:
∀i\
p, A\[j\]≥A\[p\]\]\[ \\forall i \< p,\\ A\[i\] \\le A\[p\] \\quad \\forall j \> p,\\ A\[j\] \\ge A\[p\] \]\[∀i\
p, A\[j\]≥A\[p\]
关键点:
- 只保证"左右关系正确"
- 不保证内部有序
👉 这是最容易误解的地方
🔸 3.3 递归(Recursion)
定义:
函数调用自身解决子问题
在快排中的作用:
- 对左区间继续排序
- 对右区间继续排序
🔸 3.4 原地排序(In-place)
定义:
不依赖额外线性空间
快排特点:
- 通过交换完成排序
- 仅使用常数额外空间(不计递归栈)
🔸 3.5 稳定性(Stability)
定义:
相等元素排序后相对顺序是否保持
结论:
快速排序不稳定
4. 算法结构
4.1 主过程
text
QuickSort(A, l, r):
if l < r:
p = Partition(A, l, r)
QuickSort(A, l, p-1)
QuickSort(A, p+1, r)
4.2 划分函数(Lomuto)
text
Partition(A, l, r):
pivot = A[r]
i = l - 1
for j = l to r-1:
if A[j] ≤ pivot:
i = i + 1
swap(A[i], A[j])
swap(A[i+1], A[r])
return i + 1
5. 核心机制(教学重点)
5.1 三个逻辑区间
在 partition 过程中,数组被划分为:
| 区间 | 含义 |
|---|---|
| (A[l..i]A[l..i]A[l..i]) | ≤ pivot |
| (A[i+1..j−1]A[i+1..j-1]A[i+1..j−1]) | > pivot |
| (A[j..r−1]A[j..r-1]A[j..r−1]) | 未处理 |
5.2 循环不变量(Loop Invariant)
在每轮循环开始时成立:
A\[l..i\]≤pivot,A\[i+1..j−1\]\>pivot\]\[ A\[l..i\] \\le pivot,\\quad A\[i+1..j-1\] \> pivot \]\[A\[l..i\]≤pivot,A\[i+1..j−1\]\>pivot
意义:
- 保证算法过程始终正确
- 是证明正确性的关键工具
5.3 Partition 的本质
不是排序,而是:
把一个元素(pivot)放到它最终应该在的位置
6. 正确性(简要证明)
6.1 Partition 正确性
循环结束后:
- 左侧元素全部 ≤ pivot
- 右侧元素全部 ≥ pivot
- pivot 被交换到正确位置
6.2 递归正确性
基于归纳法:
- 子问题规模更小
- 子问题正确排序
- 整体有序
7. 时间复杂度
7.1 递推式
T(n)=T(k)+T(n−k−1)+Θ(n)\]\[ T(n) = T(k) + T(n-k-1) + \\Theta(n) \]\[T(n)=T(k)+T(n−k−1)+Θ(n)
7.2 三种情况
| 情况 | 复杂度 | 原因 |
|---|---|---|
| 最优 | (n \log n) | 划分均匀 |
| 最坏 | (n^2) | 划分极端 |
| 平均 | (n \log n) | 随机分布 |
🔹 为什么是 (n \log n)
- 每层处理 (n) 个元素
- 层数约为 (\log n)
8. 空间复杂度
来源:递归调用栈
| 情况 | 空间复杂度 |
|---|---|
| 平均 | (\log n) |
| 最坏 | (n) |
9. 枢轴选择对性能的影响
🔸 9.1 固定选择
- 简单
- 易退化
🔸 9.2 随机选择
作用:
- 打乱输入结构
- 避免极端划分
🔸 9.3 三数取中
降低偏斜划分概率
10. 三路划分(进阶)
动机:
存在大量重复元素时:
- 普通快排效率下降
解决:
划分为:
\
效果:
减少递归规模
11. 与其他排序对比
| 算法 | 时间 | 空间 | 稳定 |
|---|---|---|---|
| 快排 | 平均 (nlognn \log nnlogn) | 原地 | 否 |
| 归并 | (nlognn \log nnlogn) | 额外空间 | 是 |
| 堆排 | (nlognn \log nnlogn) | 原地 | 否 |
12. 常见错误
❌ 错误1:认为 partition 后数组已排序
👉 实际只完成"分区"
❌ 错误2:递归区间写错
错误:
QuickSort(A,l,p)\]\[ QuickSort(A, l, p) \]\[QuickSort(A,l,p)
正确:
QuickSort(A,l,p−1)\]\[QuickSort(A, l, p-1)\]\[QuickSort(A,l,p−1)
❌ 错误3:不理解 i 的含义
i 表示:
$\text{"≤ pivot 区域的右边界"}$
13. 关键结论
- 快排核心是 partition
- pivot 决定效率
- 平均复杂度 (n \log n)
- 非稳定排序
- 原地算法