一.快速排序:
1.得到题目之后,设立一个中间的点,左边l,右边r,中间的点x=(l+r)<<2。
2.从左(i=l-1)右(j=r+1)两边分别向中间出发,得到两个子区间。判断:如果左面的i在数组q中的值比x要小,则i向右进一位,与此同时j也在做相应的方法。继续判断下一位的数是否比x要小,若小,则再进一位,若大,则不执行,执行下方的递归函数,使左面开始的i和j重新获得递归位置,继续判断。
3.递归处理两个区间的问题。
题目:
给定你一个长度为 n 的整数数列。请你使用快速排序对这个数列按照从小到大进行排序。并将排好序的数列按顺序输出。
输入格式
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在 1∼109 范围内),表示整个数列。
输出格式
输出共一行,包含 n 个整数,表示排好序的数列。
数据范围
1≤n≤100000
输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
代码模板:
#include <iostream>
using namespace std;
const int N = 1000010;
int q[N];
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
quick_sort(q, 0, n - 1);
for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);
return 0;
}
总结快排思路:
有数组 q, 左端点 l, 右端点r
确定划分边界 x
将 q 分为 <=x 和 >=x 的两个小数组
ii 的含义: ii 之前的元素都 ≤x≤x, 即 q[l..i−1]q[l..i−1] ≤x≤x
jj 的含义: jj 之后的元素都 ≥x≥x, 即 q[j+1..r]q[j+1..r] ≥x≥x
结论: while 循环结束后, q[l..j]q[l..j] ≤x,q[j+1..r]≤x,q[j+1..r] ≥x≥x
简单不严谨证明:
whilewhile 循环结束时, i≥j
若 i>j , 显然成立
若 i=j
∵最后一轮循环中两个 do−whiled循环条件都不成立
∴ q[i]≥x,q[j]≤xq
∴ q[i]=q[j]=xq
∴ 结论成立
递归处理两个小数组