原理
基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
基数排序的主要思路:将所有待比较数值(注意,必须是正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始, 依次进行一次稳定排序(注意必须是稳定的),这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
实现方法
最高位优先(Most Significant Digit first)法,简称MSD法:先按k1排序分组,同一组中记录,关键码k1相等,再对各组按k2排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd对各子组排序后。再将各组连接起来,便得到一个有序序列。
最低位优先(Least Significant Digit first)法,简称LSD法:先从kd开始排序,再对kd-1进行排序,依次重复,直到对k1排序后便得到一个有序序列。
LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。这里以LSD法为例。
具体实现
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef struct node{ //定义结点
int data;
int next; //静态链表,空指针默认为-1
}Node;
int data[101]; //待排序的数组
Node bucket[10]; //桶数组
Node d[101]; //将待排序的数组构造成Node类型的数组
int n; //待排序数组的数的个数
int getdigit(){ //获取数组中最多的位数
int max=1;
for(int i=0;i<n;i++){
int x=data[i];
int num=1;
while(x/10){
x/=10;
num++;
}
if(num>max)
max=num;
}
return max;
}
void init(){ //清空桶数组和d数组
for(int i=0;i<10;i++){
bucket[i].data=i;
bucket[i].next=-1;
}
for(int i=0;i<n;i++){
d[i].data=data[i]; //将data数组中的数顺序地赋给d数组
d[i].next=-1;
}
}
void Radixsort(){
int digit=getdigit(); //数组中的数的位数的最大值
int key=1;
for(int i=0;i<digit;i++){ //装桶,出桶的次数
init();
for(int i=n-1;i>=0;i--){ //按从大到小的顺序装桶
int a=(d[i].data/key)%10;
d[i].next=bucket[a].next;
bucket[a].next=i;
}
int b=0;
for(int i=0;i<10;i++){ //对桶数组从上到下出桶到data数组中去
if(bucket[i].next!=-1){
int p=bucket[i].next;
data[b++]=d[p].data;
while(d[p].next!=-1){
data[b++]=d[d[p].next].data;
p=d[p].next;
}
}
}
key*=10; //key值乘以10
}
}
void print(){ //输出数组
for(int i=0;i<n;i++)
printf("%d ",data[i]);
printf("
");
}
int main(){
printf("Please input the size of array:");
scanf("%d",&n); //输入数组元素的个数
for(int i=0;i<n;i++)
scanf("%d",&data[i]);
Radixsort();
print();
return 0;
}