声明
本文资料参考acwing算法基础课
地址:https://www.acwing.com
概述
- 解决问题:求一个数组排序问题
- 平均时间复杂度为O(nlogn)
模板记忆
这个模板分为四个部分:
- 终:递归的终点
- 初:初始化指针+枢轴
- 移:移动指针,由3个while + 一个if swap组成
- 递归:递归两侧
注意的点:
- 初始的x是可以改的:q[l] 或 q[r] 或 q[l + r >> 1] 或 q[l + r + 1 >> 1]
- 递归的中点是可以改的:j 和 j + 1 或 i - 1 和 i
- 其中q[l] 和 q[l + r >> 1] 需要用j 和 j + 1,q[r] 和 q[l + r + 1 >> 1] 需要用 i - 1 和 i
模板代码
const int N = 100010;
int q[N];
void quick_sort(int q[], int l, int r) // 对于数组q,对[l, r]进行快速排序
{
// 终
if (l >= r) return; // 当l大于等于r的时候,[l, r]不存在,所以return掉,所以下面的[l, r]都是有意义的
// 初
int i = l - 1, j = r + 1, x = q[l + r >> 1]; // 初始化两个指针i和j,分别是l - 1和r + 1,x是快排的枢轴。
// 移
while (i < j) // i和j指针的意义是:它们曾经扫过的数(不包括现在的指向)都严格满足小于等于x 和 大于等于x,
// 注意这里的等号是因为当指针i或j扫到等于x的数停止时,经过一轮swap,指针会跳过这个数字。
{
while (q[ ++ i] < x); // 把i指针移动到q[i] >= x的第一个位置
while (q[ -- j] > x); // 把j指针移动到q[j] <= x的第一个位置
if (i < j) swap(q[i], q[j]);
// if (i <= j) swap(q[i], q[j]); // 这里也可以写成<=,因为i == j的时候,swap没有影响
}
// 递归
// 结束上一个while的时候,j的右边都小于等于x,i的左边都大于等于x,并且每个数都被i或者j扫过了。
quick_sort(q, l, j); // 这里递归中心选择j是因为x取值的时候是自动向下取整
// 比如当数组只有两个不等的有序数,那么最后i和j都会指向第一个数
// 这时候用j的话没事,用i的话会导致死循环。
quick_sort(q, j + 1, r);
}