基数排序
基数排序的思想总体上就是把一组数中的所有数按照个十百位来改变在数组中的位置,分配十个桶(存放数的容器)对应0~9。比如在比较个位数时,把个位数为0的所有数放在第一个桶内,个位数为1的数放在第二个桶内,依次放入。在所有的数放完之后,此时数组内的数已经改变了位置,再比较十位数,重复上述操作,直到最大位数。
通过三次存入桶的操作后,所有的数变有序了。如果数中还有千位,则应该还要操作一次。即对应数有多少位来进行操作。
代码中使用链式队列来作为桶,因为不知道一个桶内要存放多少数。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define M 3 //定义一个数最多只有三位 4 #define RAX 10 //定义十个桶 5 6 typedef struct node{ //每个节点中都要一个数 7 int key[M]; //这个数组是存放一个数的个十百位上的数 8 struct node *next; //每个桶都是一个链队列 9 }Rnode; 10 11 Rnode *f[RAX],*r[RAX]; //f是队列的头指针,r是队列的尾指针 12 13 //给每个链队列分配空间 14 void initBarrel(Rnode *f[RAX],Rnode *r[RAX]){ 15 int i; 16 for(i=0;i<RAX;i++){ 17 f[i] = (Rnode *)malloc(sizeof(Rnode)); 18 r[i] = (Rnode *)malloc(sizeof(Rnode)); 19 } 20 } 21 22 //初始化一个链表 23 Rnode *setList(int num[],int n){ 24 25 Rnode *p,*head = (Rnode *)malloc(sizeof(Rnode)); 26 head->next = NULL; 27 28 int i,j; 29 for(i=0;i<n;i++){ 30 p = (Rnode *)malloc(sizeof(Rnode)); 31 p->key[0] = num[i]/100; //把一个数的个十百位分别存放到数组中,百位在最前 32 p->key[1] = num[i]/10%10; //十位在中间 33 p->key[2] = num[i]%10; //个位在最后 34 p->next = head->next; //此处使用头插法,方便后面的操作 35 head->next = p; 36 } 37 38 return head; 39 40 } 41 42 //把数放入桶中 43 void distribute(Rnode *head,int n){ 44 //这个n就是指定了数的哪个位数,假如是个位,就把数的个位与桶下标相同的这个数放入到那个桶里去 45 int i,j; 46 for(i=0;i<RAX;i++){ //使每组 r[i]、f[i]作为此组一个队列的头尾指针 47 r[i]->next = NULL; 48 f[i] = r[i]; 49 } 50 51 head = head->next; //此处要用两个指针来取值 52 Rnode *p = head; 53 54 while(p!=NULL){ 55 head = head->next; //head指在p下一个位置,前面断的部分影响不到head指针继续往后走 56 j = p->key[n]; //根据这个节点中,数的个十百位来存放到指定的桶 57 r[j]->next = p; //这里是队列的入队操作 58 r[j] = p; 59 r[j]->next = NULL; //此时链表在p指针处已经断了,因为p->next=NULL 60 p = head; //p指向head,继续向后遍历 61 } 62 63 } 64 65 //把桶里的数拿出来 66 Rnode *collect(){ 67 68 Rnode *t,*p,*head = (Rnode *)malloc(sizeof(Rnode)); 69 head->next = NULL; 70 71 int i,j; 72 for(i=0;i<RAX;i++){ //对每个桶都要遍历 73 t = f[i]->next; 74 while(t!=NULL){ //遍历这个桶里的所有数 75 p = (Rnode *)malloc(sizeof(Rnode)); 76 for(j=0;j<M;j++) 77 p->key[j] = t->key[j]; 78 79 p->next = head->next; //把桶中的数取出存放到链表里,存放方式还是头插法 80 head->next = p; 81 t = t->next; 82 } 83 } 84 return head; 85 } 86 87 void main(){ 88 89 int i,num[10] = {121,231,12,322,901,678,765,875,661,410}; 90 91 Rnode *p,*head = setList(num,10); 92 93 initBarrel(f,r); //给每个链队列分配空间 94 95 for(i=M-1;i>=0;i--){ 96 distribute(head,i); //每次传入不同的数,用于对数字的个十百位。 97 head = collect(); //把桶中的数取出存方法到链表里,存放方式还是头插法 98 } 99 100 p = head->next; 101 while(p!=NULL){ //其实打印的顺序是反的,因为用的头插法 102 printf("%d%d%d ",p->key[0],p->key[1],p->key[2]); 103 p = p->next; 104 } 105 }