算法描述
前面所讨论的简单排序、快速排序和堆排序等等排序算法都假定待排序的记录只有一个关键字。基数排序可以处理多关键字排序问题。可以将一副纸牌的排序问题看成一个基于两个关键的排序问题,这两个关键字分别为纸牌的花色和面值。基数排序可以有两种处理关键字的顺序MSD(Most Significant Digit)排序和LSD(Least Significant Digit)排序。
Q:基数排序(以整形为例),将整形10进制按每位拆分,然后从低位到高位依次比较各个位。主要分为两个过程:
(1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中)
(2)收集,再将放置在0~9号桶中的数据按顺序放到数组中
重复(1)(2)过程,从个位到最高位(比如32位无符号整形最大数4294967296,最高位10位)
以【521 310 72 373 15 546 385 856 187 147】序列为例,具体细节如下图所示:
算法实现(LSD):
输入数据以单链表形式给出
#define MAX_DIGIT 3
#define RADIX_SIZE 10
typedef struct listNode *plist;
typedef struct listNode
{
int key;
plist link;
};
int getDigit(int num,int pos)
{
int temp = 1;
for(int i=0;i<pos-1;i++)
temp *= RADIX_SIZE;
return (int)(num/temp)%RADIX_SIZE;
}
plist radixSort(plist ptr)
{
plist front[RADIX_SIZE],rear[RADIX_SIZE];
int i,j,digit;
for (i=1;i<=MAX_DIGIT;i++)
{
/* init front[] and rear[]. */
for(j=0;j<RADIX_SIZE;j++)
front[j]=rear[j]=NULL;
/* allocate ptr to front[]...rear[]. */
while(ptr)
{
digit = getDigit(ptr->key,i);
if(!front[digit])
front[digit] = ptr;
else
rear[digit]->link = ptr;
rear[digit] = ptr;
ptr = ptr->link;
}
/* reestablish the linked list for the next pass */
ptr = NULL;
for(j=RADIX_SIZE-1;j>=0;j--)
if(front[j]){
rear[j]->link = ptr; ptr = front[j];
}
}
return ptr;
}
测试数据以及每轮测试的中间结果:
参考文章:http://blog.csdn.net/cjf_iceking/article/details/7943609