基数排序(英语:Radix sort)是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
它是这样实现的:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
参考 《数据结构》(C语言版)--严蔚敏编著 教材 P288,用C语言实现经典的基数排序算法。用例也参考教材P287.
#include <stdio.h>
#define RADIX 10 //关键字基数,一般为10进制
#define MAX_SPACE 100 //数组最大容量
/*--- 静态链表 ---*/
struct SLCell{
int keys; //关键字 用于存储待排序的数
int next;
}r[MAX_SPACE];
typedef int ArrType[RADIX];
void Distribute(int base,ArrType &f,ArrType &e) //分配过程
{
int i,j;
for(i=0;i<RADIX;++i)f[i]=0; //各字表初始化为空
for(i=r[0].next;i;i=r[i].next)
{
j=(r[i].keys/base)%10; //求r[i].keys关键字 的映射
if(!f[j])f[j]=i; //如果该字表为空,则头指针指向它
else r[e[j]].next=i; //如果不为空,令字表中最后一个数据的next指向它
e[j]=i; //更新尾指针
}
}
void Collect(ArrType &f,ArrType &e) //收集过程
{
int j;
for(j=0;!f[j];++j); //找第一个非空字表
r[0].next = f[j]; //令r[0].next指向第一个非空字表的第一个结点
int t=e[j]; //t代表目前字表链接起来后的最后一个结点
while(j<RADIX-1) //注意!为RADIX-1 ;若为j<RADIX 会溢出错误
{
for(++j;j<RADIX-1 && !f[j];++j); //找下一个非空字表
if(f[j]){r[t].next=f[j];t=e[j];} //链接两个非空字表
}
r[t].next = 0; //t指向最后一个非空字表的最后一个结点
}
void RadixSort(int keynum)
{
ArrType f,e;
int i,base=1;
for(i=0;i<keynum;++i) //按LSD(最低位优先)依次进行分配和收集
{
Distribute(base,f,e);
Collect(f,e);
base = base * 10;
}
}
int main()
{
freopen("in.txt","r",stdin);
int n; //n代表要排序的数据个数
scanf("%d",&n);
int i,mmax=0;
for(i=1;i<=n;i++)
{
scanf("%d",&r[i].keys);
r[i].next=i+1; //初始化链表为一个接一个向后链接
if(mmax<r[i].keys)mmax=r[i].keys;
}
r[0].next=1; //第一个数据结点为 1
r[n].next=0;
printf("Before RadixSort:\n"); //输出排序前数组
for(i=r[0].next;i;i=r[i].next)
printf("%d ",r[i].keys);
printf("\n");
//printf("mmax: %d\n",mmax);
int keynum=0;
while(mmax>0) //求得最大值mmax的位数keynum
{
mmax=mmax/10;
keynum++;
}
//printf("keynum: %d\n",keynum);
RadixSort(keynum);
printf("After RadixSort:\n"); //输出排序后数组
for(i=r[0].next;i;i=r[i].next)
printf("%d ",r[i].keys);
printf("\n");
return 0;
}
in.txt 输入文件:
10
278 109 63 930 589 184 505 269 8 83
运行结果: