基数排序的发明可以追溯到1887年赫尔曼何乐礼在打孔卡片制表机上的贡献。
实现原理:将所有待比较的正整数统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始进行基数位10的计数排序,一直到最高位计数排序完后,数列就变成了一个有序数列(利用了计数排序的稳定性)
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=100;
const int base=15;
const int dn=3;
int n,s[maxn],b[maxn],c[maxn];
int getdigit(int i,int d)
{
int radix[]={1,1,10,100};
return (s[i]/radix[d])%10;
}
void countingsort(int d)
{
for(int i=0;i<base;i++){
c[i]=0;
}
for(int i=0;i<n;i++){
c[getdigit(i,d)]++;
}
for(int i=1;i<base;i++){
c[i]=c[i]+c[i-1];
}
for(int i=n-1;i>=0;i--){
int digit=getdigit(i,d);
b[--c[digit]]=s[i];
}
for(int i=0;i<n;i++){
s[i]=b[i];
}
}
void lsdradixsort()
{
for(int d=1;d<=dn;d++){
countingsort(d);
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&s[i]);
}
lsdradixsort();
for(int i=0;i<n;i++){
cout<<s[i]<<" ";
}
cout<<endl;
return 0;
}
/*
7
329 457 657 839 436 720 355
*/
基数排序的复杂度是O(n*dn),其中n是待排序元素的个数,dn是数字位数。这个时间复杂度不一定优于O(nlogn),dn的大小取决于数位的选择,和待排序数据所属数据类型的全集的大小。
如果考虑和比较排序进行对照,基数排序的形式复杂度虽然不一定更小,但由于不进行比较,因此其基本操作的代价更小,所以基数排序一般要快于基于比较的排序,比如快速排序。由于整数也可以表达字符串(比如名字或日期)和特定的浮点数,所以基数排序并不是只能用于整数排序。