已经学习了简单的几种排序,在研究后缀数组的时候,发现里面要用到基数排序,就研究了一下。总共花了三个小时左右吧,实现了一种简单的代码。

   先总结一下思路吧!

   基数排序其实非常简单。

解法 
  基数排序的方式可以采用LSD(Least sgnificant digital)或MSD(Most sgnificant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。 
  以LSD为例,假设原来有一串数值如下所示: 
  73, 22, 93, 43, 55, 14, 28, 65, 39, 81 
  首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中: 
  0 
  1 81 
  2 22 
  3 73 93 43 
  4 14 
  5 55 65 
  6 
  7 
  8 28 
  9 39 
  接下来将这些桶子中的数值重新串接起来,成为以下的数列: 
  81, 22, 73, 93, 43, 14, 55, 65, 28, 39 
  接着再进行一次分配,这次是根据十位数来分配: 
  0 
  1 14 
  2 22 28 
  3 39 
  4 43 
  5 55 
  6 65 
  7 73 
  8 81 
  9 93 
  接下来将这些桶子中的数值重新串接起来,成为以下的数列: 
  14, 22, 28, 39, 43, 55, 65, 73, 81, 93 
  这时候整个数列已经排序完毕;如果排序的对象有三位数以上,则持续进行以上的动作直至最高位数为止。 
  LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好,MSD的方式恰与LSD相反,是由高位数为基底开始进行分配,其他的演算方式则都相同。 

(注:以上红色文字选自:http://blog.csdn.net/normallife/article/details/3848992)

但是作者上面的代码实现我个人觉得太麻烦了,就自己写一遍。还是对指针不熟悉啊!指针的问题纠结了一下下。

 

  1. #include<stdio.h> 
  2. #include<stdlib.h> 
  3. typedef struct Bucket{ 
  4.     int val; 
  5.     struct Bucket *next; 
  6.     Bucket(){ 
  7.         next=NULL; 
  8.     } 
  9. }bucket;//这个桶:实质上是一个链表数组 
  10. bucket b[10]; 
  11.  
  12. void basesort(int a[10],int m){//从右到左,对第i数排序 
  13.     int i,j;//循环变量,不解释 
  14.     int yu=1,chu=1;//取a[i]的m位时用到的两个变量 
  15.  
  16.     //第一步:把取位需要用到的变量值求出来 
  17.     for(i=0;i<=m;i++){ 
  18.         yu*=10; 
  19.     } 
  20.     chu=yu/10; 
  21.  
  22.     //第二步:把a[i]里的数 装进 桶里面去 
  23.     int pos; 
  24.     bucket *p; 
  25.     for(i=0;i<10;i++){ 
  26.         /* 
  27.          * 对一个整数 取其特定位上的数值,比如123取十位,则用123%100/10就可以了 
  28.          * */ 
  29.         pos=a[i]%yu/chu;//取得m位数上的值 比如 100 m=2(m从零开始),则表示取百位上的数,为1 
  30.         p=&b[pos]; 
  31.         bucket *bi=new bucket();//这里我用malloc就不行,不知道为什么 
  32. //      bucket *bi=(bucket*)malloc(sizeof(bucket)); 
  33.         while(p->next!=NULL){ 
  34.             p=p->next; 
  35.         }//这里对链表采用加到尾部的方法 
  36.         bi->val=a[i]; 
  37.         p->next=bi; 
  38.     } 
  39.  
  40.     //第三步:把桶里面的数依次放回到数组中去,并把桶清空 
  41.     i=0,j=0; 
  42.     p=b[0].next;//链表的头结点为空 
  43.     bucket *f;//用来释放空间 
  44.     while(i<10&&j<10){ 
  45.         while(p!=NULL){ 
  46.             a[i++]=p->val;//把桶中的数据放回到数组中 
  47.             f=p;p=p->next; 
  48.             delete(f);//释放空间 
  49.         } 
  50.         b[j].next=NULL;//当前桶已经查找完毕,清空,为下次存储作准备 
  51.         p=b[++j].next;//查找下一个桶 
  52.     } 
  53. int main(){ 
  54.     //数据准备(做菜:源料) 
  55.      int a[10]={10000,2,3,10,1,60,7,0,9,0}; 
  56.      int k=5;//k表示数组中最大数的位数,这里的5表示10000的位数 
  57.  
  58.      //排序:从右到左,按LSD的方式(做菜:烹饪) 
  59.      for(int i=0;i<k;i++){ 
  60.          basesort(a,i); 
  61.      } 
  62.      //output(做菜:出菜) 
  63.      for(int i=0;i<10;i++) 
  64.          printf("%d ",a[i]); 
  65.     return 0; 
好了,问题来了:如果数据是负数就能不能直接这样做呢?答案当然是不行的,但是用这种思想依然是可以解决滴!