36排序算法之基数排序
排序算法之基数排序
基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
原理:用整理扑克牌的例子说明基本原理。
示例
(1)整数排序
将整数(元素)看成多元组(数字串)
每个分量(一位)有m(10)种不同的取值(0,1,2,3,…)
编号为0,1,2,…,m-1元素的有序次序===多元组的“字典次序”。
(2)字符串排序
例如,将英文单词排成字典次序:
for end else goto file int new case char and
长度不足4个字母的单词尾部加空格符 □。
算法的实现:
(1)选用的数据结构
1)数据采用链式存储,总队列queue
2)结点值域为数组a[k],每个分量a[j]满足
0≤a[j]的序号值≤m-1(j=0,2,…,k-1)
3)m个分队列用于分组q[0],q[1],q[2],…,q[m-1]。
(2)算法描述
步骤1)置分量下标j等于k-1
步骤2)[分组]
①将各分队列q[0],q[1],q[2],…,q[m-1]置空。
②依次从总队列中取下元素a,设其第j个分量a[j]的序号值为t,将该元素放在分队列q[t]的尾部,反复如此,直到把总队列中元素取完。
步骤3)[收集]按分队列的序号由小到大,依次将分队列q[0],q[1],q[2],…,q[m-1]首尾相接,组成新的总队列。
步骤4)j=j-1,若j<0,排序结束;否则,转步骤2。
基数排序实现算法:
(1)类型定义
typedef struct node //定义结点类型
{ char a[k]; //值域和分量类型
struct node *next; // 链域
} *ptr; // 指针类型名
(2)实现程序
void radix_sort(ptr &h,int k)
{
int i,j,y;
char x;
ptr p;
struct {ptr head,tail;} q[m];
for(j=k-1;j>=0;j- -)
{
for(i=0;i<m;i++)
q[i].head=NULL;
while(h)
{
x=h->a[j];
y=value(x); //将x换算成序号值
if(q[y].head==NULL)
q[y].head=h;
else
q[y].tail->next=h;
q[y].tail=h;
h=h->next;//取总队列下一个元素
} //分组完毕
i=0;
while(q[i].head==NULL)
i++;
h=q[i].head;
p=q[i].tail;
for(i++;i<m;i++)
if(q[i].head)
p->next=q[i].head,p=q[i].tail;
p->next=NULL;
}
}
源代码: #include<math.h> testBS() { inta[] = {2, 343, 342, 1, 123, 43, 4343, 433, 687, 654, 3}; int *a_p = a; //计算数组长度 intsize = sizeof(a) / sizeof(int); //基数排序 bucketSort3(a_p, size); //打印排序后结果 inti; for(i = 0; i < size; i++) { printf("%d\n", a[i]); } intt; scanf("%d", t); } //基数排序 voidbucketSort3(int *p, intn) { //获取数组中的最大数 intmaxNum = findMaxNum(p, n); //获取最大数的位数,次数也是再分配的次数。 intloopTimes = getLoopTimes(maxNum); inti; //对每一位进行桶分配 for(i = 1; i <= loopTimes; i++) { sort2(p, n, i); } } //获取数字的位数 intgetLoopTimes(intnum) { intcount = 1; inttemp = num / 10; while(temp != 0) { count++; temp = temp / 10; } returncount; } //查询数组中的最大数 intfindMaxNum(int *p, intn) { inti; intmax = 0; for(i = 0; i < n; i++) { if(*(p + i) > max) { max = *(p + i); } } returnmax; } //将数字分配到各自的桶中,然后按照桶的顺序输出排序结果 voidsort2(int *p, intn, intloop) { //建立一组桶此处的20是预设的根据实际数情况修改 intbuckets[10][20] = {}; //求桶的index的除数 //如798个位桶index=(798/1)%10=8 //十位桶index=(798/10)%10=9 //百位桶index=(798/100)%10=7 //tempNum为上式中的1、10、100 inttempNum = (int)pow(10, loop - 1); inti, j; for(i = 0; i < n; i++) { introw_index = (*(p + i) / tempNum) % 10; for(j = 0; j < 20; j++) { if(buckets[row_index][j] == NULL) { buckets[row_index][j] = *(p + i); break; } } } //将桶中的数,倒回到原有数组中 intk = 0; for(i = 0; i < 10; i++) { for(j = 0; j < 20; j++) { if(buckets[i][j] != NULL) { *(p + k) = buckets[i][j]; buckets[i][j] = NULL; k++; } } } }