快速排序
快速排序
快速排序的三个步骤:
这里最重要的就是如何调整区间?
朴素做法:
我们开两个数组a[]、b[],然后把q[]数组都扫一遍。
如果大于等于分界点x,放在a[]里。否则放在b[]里。
最后,把a[]、b[]都放回q[]。
优美做法:
1.选择一个分界点x = q[l] q[r] q[l + r >> 1] (注意不要取q[l] q[r]会TLE,acwing数据加强了)
2.取两个指针i、j在l、r的两侧。即i = l-1,j = r+1。
每次i++,判断q[i]<x满足则前往下一个,否则就停止。
每次j--,判断q[j]>=x满足则前往下一个,否则就停止。
判断i < j,则交换q[i]、q[j]。
3.递归左右两段。
如果选择i分段,则x != q[l].
如果选择j分段,则x != q[r].
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 100010;
int n;
int q[N];
void quick_sort(int q[],int l,int r)
{
if (l >= r) return;
int x = q[(l+r)/2],i = l - 1,j = r + 1;
//x分界点任意取l、r、mid
//i、j指针指向的是边界的两侧
while (i < j)
{
do i ++ ;while (q[i] < x);
do j -- ;while (q[j] > x);
if (i < j) swap(q[i],q[j]);
}
//递归循环分好的两区间用
//i划分:l,i-1 i,r 但是x不能用q[l]死循环
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;
}
时间复杂度
每层都要扫一遍即n次,每次取分界点期望在n/2,到把n除到1,大约需要递归logn次。
平均时间复杂度nlogn,最坏时间复杂度n^2.