排序算法可以说是从语言步入算法的第一道坎了,其中最有代表性的莫过于快排。这里模拟库函数自带sort的调用方式,写起来相当自然清爽。
朴素快速排序算法的复杂度最好为O(nlogn),最坏时能达到O(n²)
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
bool cmp(int x,int y)
{
return x<y;
}
template<class T> //定义一个类模板
void quick_sort(T *a,T *b,bool compare(T,T)) //对[a,b)中的元素进行以compare为法则的排序
{
int m=b-a,k=rand()%m; //随机优化
T key=a[k];
swap(a[0],a[k]);
int i=0,j=m-1;
while(i<j)
{
while(i<j && compare(key,a[j]))j--;
if(i<j) a[i++]=a[j];
while(i<j && compare(a[i],key))i++;
if(i<j) a[j--]=a[i];
}
a[i]=key;
if(i>1) quick_sort(a,a+i,compare);
if(i<m-1) quick_sort(a+i+1,b,compare);
return;
}
int main()
{
int m;
scanf("%d",&m);
int a[100003];
FOR(i,1,m)scanf("%d",&a[i]);
quick_sort(a+1,a+m+1,cmp);
FOR(i,1,m)printf("%d ",a[i]);
printf("\n");
return 0;
}
上面这个流程图会使算法清晰很多,其实快排可以简单地归结为四个字“挖坑填数”。
比如说朴素的快排,选取第一个元素为标准,也就是说把第一个元素“挖”了出来。然后从右端找到更小的数“填”进去,那么右端也空了一个坑。再从左边继续寻找……如此周而复始,直到左右指针重合,把第一个挖出来的元素填上,然后以这个重合的位置把区间分成两半进行递归……
然后这个随机的快排也是一样的道理,只不过它多了一步操作,随机选取一个元素作为标准,“挖”出来,再把第一个元素填进去。