快速排序及模板
1. 思想
快速排序是基于分治法的思想。首先给定一组数,使用快速排序对其进行排序的话,过程如下:
1. 确定分界点:q[l],q[(l+r)/2],q[r]或者随机都可以
2. 调整区间:如果我们以x为分界点的话,之后我们将区间分为两半。注意,这两半未必长度相等。使得左区间里面的数都小于等于x,右区间里面的数都大于等于x。在调整区间的时候,x不一定只有一个,且既有可能位于左区间也有可能位于右区间。
3. 递归处理左右两段,进而排序完成。

上述过程中,最难的就是调整区间的部分。
有一种暴力的做法可以调整区间。
1. 先开两个额外数组a和b
2. 扫描整个数组q,使得小于等于x的放在a数组,大于x的放在b数组。
3. 扫描过后,将a数组的内容放在q数组中,在将b数组的内容放在q数组中。这样就划分完成了。
上述的做法,虽然使得空间复杂度提高,但是时间复杂度很良好。是O(n)
还有一种比较优美的调整区间的做法。
1. 初始化两个指针i和j,指向数组q的第一个和最后一个元素。
2. 两个指针都往中间靠拢,规则就是:首先移动i,如果q[i] < x 那么就往中间走,直到q[i] >=x 为止。然后,再移动j,如果q[j] > x 那么就往中间走,直到q[j] <=x 为止。
3. 当移动完i和j之后,如果i和j没有相遇或者交错,那么就交换q[i]和q[j]。交换后,i和j都分别需要移动一格,之后再进行上述过程。如果i和j相遇或者交错,不需要交换q[i]和q[j],代表划分区间完成。
4. 我们以j为标准来划分区间,我们可以发现:l~j是左区间,里面的数都小于等于x。j+1~r是右区间,里面的数都大于等于x。
需要注意的是,在任何情况下,i左边的数(不包括i),都小于等于x。j右边的数(不包括j),都大于等于x。
上述的做法,没有开辟任何额外空间,空间复杂度很低,同时时间复杂度也很良好。是O(n)
我们可以通过一个案例[31235],来完成上述过程。(略)
2. 模板
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);
}
3. 题目
地址:https://www.acwing.com/problem/content/787/
#include <iostream>
#include <cstdio>
using namespace std;
void quick_sort(int q[],int l,int r){
if(l>=r){
return;
}
int i = l-1;
int j = r+1;
int x = q[(l+r) >> 1];
while(i < j){
do{i++;}while(q[i] < x);
do{j--;}while(q[j] > x);
if(i < j){
int temp = q[i];
q[i] = q[j];
q[j] = temp;
}
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
int main(){
int n;
int q[100010];
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;
}
地址:https://www.acwing.com/problem/content/788/
#include <iostream>
#include <cstdio>
using namespace std;
void quick_sort(int q[],int l,int r){
if(l >= r){
return;
}
int i = l-1;
int j = r+1;
int x = q[(l+r)>>1];
while(i < j){
do{i++;}while(q[i] < x);
do{j--;}while(q[j] > x);
if(i < j){
int temp = q[i];
q[i] = q[j];
q[j] = temp;
}
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
int main(){
int n,k;
int q[100010];
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]);
return 0;
}
作者:gao79138
链接:https://www.acwing.com/
来源:本博客中的截图、代码模板及题目地址均来自于Acwing。其余内容均为作者原创。
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。