快速排序步骤
- 确定分界点x(q[l]或q[r])
- 调整区间(一段元素都
,另一段元素都)
- 递归左右两端
核心模版
void quick_sort(int q[], int l, int r) {
if (l >= r) return;
int x = q[l], i = l - 1, j = 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]);
else quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
quick_sort(q, 0, n - 1); // 调用快排
说明
一:当分界点选择x = q[l] 涉及到了左边界,所以递归必须写成quick_sort(q, l, j), quick_sort(q, j + 1, r);
形式
- 如果写成此时写成了
quick_sort(q, l, i - 1), quick_sort(q, i, r);
那么可能会出现死循环 - 比如:长度为2的区间[1, 2],如果取x = q[l],那么使用函数quick_sort(q, 0, 1),然后i=0,j=0,没有进行swap,左右递归是quick_sort(q, 0, -1), quick_sort(q, 0, 1); 你会发现总有个区间会不断递归下去,而区间一直是[1, 2],永远到不了出口
二:若把边界改为 x = q[r]右边界, 则需用quick_sort(q, l, i - 1), quick_sort(q, i, r);
三:
do i++; while (q[i] < x);
出循环q[i]>=xdo j--; while (q[j] > x);
出循环q[j]<=x- 这样交换以后,可以满足性质一段元素都
,另一段元素都
例题
题目描述:
对一个数组从小到大排序
输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
C++代码
#include <iostream>
using namespace std;
const int N = 1e5 + 7;
int q[N];
// 快速排序:确认分界点,调整区间,递归左右两段
void quick_sort(int q[], int l, int r) {
if (l >= r) return;
int x = q[l], i = l - 1, j = 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]);
else quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
}
// quick_sort(q, 0, n - 1);
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i ++) {
cin >> q[i];
}
quick_sort(q, 0, n - 1);
for (int i = 0; i < n; i ++) {
cout << q[i] << " ";
}
}