说到排序大家会想到什么呢
是 的选择冒泡排序
还是 的快排,归并排序等等
还是
的希尔排序虽然我不会
还是对空间要求大的 的桶排?
如果想“快速”的对一个数列进行排序,最快的肯定是桶排,但是如果 那桶排他就死了
这里给大家介绍一种高级的 的排序算法——基数排序
当然你也不要高兴的太早,基数排序名义上是
但是他的常数非常的大,详细写大概是这个样子的: ,其中r表示 ,m表示容器个数,也就是10,等会下文会讲到
所以其实我们看到基数排序是最后时间复杂度和快排的 也差不多
下面来讲这个算法
首先比较这列数的个位,把个位相同的放到一个桶里(像桶排一样)
然后把他们按照现在正在排的那一位从小到大(或从大到小),倒出来
一直重复执行 (上文提到的r)遍
最后得到的就是最终要的序列。
我们用图来解释一下
比如我们要排一列数
20,6,5,505,9,1,17,7,91
那么我们要排三次序
第一次排序
桶内数 | |
---|---|
0 | 20 |
1 | 1,91 |
2 | |
3 | |
4 | |
5 | 5,505 |
6 | 6 |
7 | 17,7 |
8 | |
9 | 9 |
然后我们按顺序取出
得到20,1,91,5,505,6,17,7,9
第二次排序
桶内数 | |
---|---|
0 | 1,5,505,6,7,9 |
1 | 17 |
2 | 20 |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | 91 |
再按顺序取出,得到1,5,505,6,7,9,17,20,91
第三次排序
桶内数 | |
---|---|
0 | 1,5,6,7,9,17,20,91 |
1 | |
2 | |
3 | |
4 | |
5 | 505 |
6 | |
7 | |
8 | |
9 |
再取出,得到1,5,6,7,9,17,20,91,505——大功告成
上代码:
# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
# include <vector>
# include <set>
# include <map>
# include <cstdlib>
# include <stack>
# include <ctime>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define mct(a,b) memset(a,b,sizeof(a))
# define gc getchar()
typedef long long ll;
const int N=1e5+5;
const int inf=0x7fffffff;
const double eps=1e-7;
template <typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,a[N];
int cnt[N],pour[N];
inline int getd(){
int d=1;
int p=10;
Rep(i,1,n){
while(a[i]>=p){
p*=10;
d++;
}
}
return d;
}
inline void radixsort(){
int d=getd();
int radix=1;
Rep(i,1,d){
memset(cnt,0,sizeof(cnt));
Rep(j,1,n){
int k=(a[j]/radix)%10;
cnt[k]++;
}
Rep(j,1,9)cnt[j]+=cnt[j-1];
_Rep(j,n,1){
int k=(a[j]/radix)%10;
pour[cnt[k]]=a[j];
cnt[k]--;
}
memcpy(a,pour,sizeof(pour));
radix*=10;
}
}
int main()
{
read(n);
Rep(i,1,n)read(a[i]);
radixsort();
Rep(i,1,n)printf("%d ",a[i]);
puts("");
return 0;
}
听说基数排序有一种位运算优化可以真正优化到
但是我也不会