前言
学习acwing的快排
快排思路
Step1:确定分界点 比如q[l]
,q[(l+r)/2]
,q[r
,随机
,一般常用前三种,但如果数据全是相同的,一般时间复杂度会从O(nlogn)
变成O(n^2)
,所以我们会选择随机
的方法确定分界点。
Step2:调整范围 设分界点 = x
,我们划分区域,<=x
在分界点的左侧,>=x
在分界点右侧。
划分区域的方法: 先设左索引
i
和右索引j
。先依此i++
,遇到q[i] >= x
时结束,然后j--
,遇到q[j] <= x
时结束,然后交换swap(q[i], q[j])
,继续i++
j--
Step3:递归处理左右两段
acwing785.快速排序
#include <iostream>
using namespace std;
const int N = 10e5 + 10;
int n, q[N];
void quick_sort(int q[], int l, int r) {
if (l >= r) return;
int i = l - 1, j = r + 1;
int index = rand() % (r - l + 1) + l;
int x = q[index];
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() {
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;
}
要想清楚,最后i
和j
结束的位置,i
和j
是挨着的,并且i = j + 1
,所以递归那样写。
练习:786.第k个数
#include <iostream>
using namespace std;
const int N = 10e5 + 10;
int n, k, q[N];
void quick_sort(int q[], int l, int r) {
if (l >= r) return;
int i = l - 1, j = r + 1;
int index = rand() % (r - l + 1) +l;
int x = q[index];
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() {
scanf("%d %d",&n, &k);
for (int i = 0; i < n; i++) {
scanf("%d", &q[i]);
}
quick_sort(q, 0, n - 1);
printf("%d", q[k - 1]);
}