快速排序(分治法)
基本步骤
①确定分界点:q[l] 或q[r] 或 q[(l+r)>>],强烈建议选择第三种作为分界点,能够避免边界问题
②调整区间,小于等于x的区间左侧,大于等于x的在区间右侧
③递归处理左右区间
代码模板
#include<iostream>
using namespace std;
const int N = 1e5+10;
int n;
int q[N];
void quick_sort(int q[],int l,int r){
if(l>=r)
return;
int x=q[(l+r)>>1],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);
/*
取中间节点作为分界点,也可以写成如下形式
quick_sort(q,l,i-1);
quick_sort(q,i,r);
*/
return;
}
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;
}
复杂度
平均时间复杂度为O(nlogn),最坏为O(n^2),但一般不会达到
快速排序的应用
链接:第k个数
#include<iostream>
using namespace std;
const int N = 1e5+10;
int n,k;
int q[N];
void quick_sort(int q[],int l,int r){
if(l>=r)
return;
int x=q[(l+r)>>1],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]);
}
if(k-1<=j) //k-1是第k小的数在排好序的数组中的下标
quick_sort(q,l,j);
else
quick_sort(q,j+1,r);
//当然也可以直接无脑排序左右区间,然后直接输出q[k-1],但时间复杂度比上面大
}
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]);
return 0;
}