快排的主要思想是分治
第一步就是确定分界点:q[l] , q[(1 + r) / 2] , q[r]
第二步是调整区间:使得第一区间的所有数都大于x,第二区间的所有数都大于等于x
那么如何实现呢?第一种方法是一种暴力做法
首先定义两个数组a[],b[],遍历q[]中l到r若q[i]<=x则将x插入a数组,若q[i]>x则将x插入b数组
最后将a,b相连则可实现时间复杂度为O(n)
显而易见这种方法并不优美,我这么优雅的人是绝对不允许我的代码如此暴力的哈哈
第二种方法则是用到两个指针 i 在左 j 在右,i j同时往中间走,边走边判断若q[i]>x则停下反之继续向右判断,若q[j]<x则停下反之继续向左判断。当i j都停下时交换两个指针对应的数值,然后继续往中间走....直到 i 和 j 相遇为止。这样就可以使ij相遇的左边都是小于x的数,右边都是大于x的数。不用开辟新建的数组来存储,非常之优雅。
因为要考虑到很多的边界问题,所以还是背个模板更有性价比。下面是在y总那里学到的模板
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);
最后就是完整的模板(来自acwing)
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int n;
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]);
}
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;
}
完结撒花