快速排序(分治)
步骤:
-
确定分界点:取左边界、取中点、取有边界、随机选取
-
调整区间:保证小于等于x的在x左边,大于等于x的在右边(重点)
-
递归处理左右两段
暴力处理:
开两个额外数组a[]和b[],扫码整个区间q[l~r],如果当前数小于x,插入到a[],如果大于x,插入到b[],最后把a[]和b[]分别放到q里。
优雅处理:
左右两个指针i和j,如果i指的数小于x,i往中间走,同理j大于x的话,j往中间走,直到i和j都走不动,i和j的值交换,继续进行。
模板:
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]);
}
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
}
快速选择算法
作用:选出第k大(小)的数
与快速排序一样,我们将输入数组进行递归划分,与快速排序不同的是,快速排序会递归处理划分的两边,而选择只处理划分一边。
#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
int a[N];
int n, k;
int quick_sort(int l, int r, int k) {
if (l == r) return a[l];
int i = l - 1, j = r + 1, x = a[l];
while (i < j) {
do i++; while (a[i] < x);
do j--; while (a[j] > x);
if (i < j) swap(a[i], a[j]);
}
int sl = j - l + 1;//左边一共多少个数
if (k <= sl) {
return quick_sort(l, j, k);
} else {
return quick_sort(j + 1, r, k - sl);
}
}
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
cout << quick_sort(1, n, k) << endl;
return 0;
}