已经学习了简单的几种排序,在研究后缀数组的时候,发现里面要用到基数排序,就研究了一下。总共花了三个小时左右吧,实现了一种简单的代码。
先总结一下思路吧!
基数排序其实非常简单。
解法
基数排序的方式可以采用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)
但是作者上面的代码实现我个人觉得太麻烦了,就自己写一遍。还是对指针不熟悉啊!指针的问题纠结了一下下。
好了,问题来了:如果数据是负数就能不能直接这样做呢?答案当然是不行的,但是用这种思想依然是可以解决滴!
- #include<stdio.h>
- #include<stdlib.h>
- typedef struct Bucket{
- int val;
- struct Bucket *next;
- Bucket(){
- next=NULL;
- }
- }bucket;//这个桶:实质上是一个链表数组
- bucket b[10];
- void basesort(int a[10],int m){//从右到左,对第i数排序
- int i,j;//循环变量,不解释
- int yu=1,chu=1;//取a[i]的m位时用到的两个变量
- //第一步:把取位需要用到的变量值求出来
- for(i=0;i<=m;i++){
- yu*=10;
- }
- chu=yu/10;
- //第二步:把a[i]里的数 装进 桶里面去
- int pos;
- bucket *p;
- for(i=0;i<10;i++){
- /*
- * 对一个整数 取其特定位上的数值,比如123取十位,则用123%100/10就可以了
- * */
- pos=a[i]%yu/chu;//取得m位数上的值 比如 100 m=2(m从零开始),则表示取百位上的数,为1
- p=&b[pos];
- bucket *bi=new bucket();//这里我用malloc就不行,不知道为什么
- // bucket *bi=(bucket*)malloc(sizeof(bucket));
- while(p->next!=NULL){
- p=p->next;
- }//这里对链表采用加到尾部的方法
- bi->val=a[i];
- p->next=bi;
- }
- //第三步:把桶里面的数依次放回到数组中去,并把桶清空
- i=0,j=0;
- p=b[0].next;//链表的头结点为空
- bucket *f;//用来释放空间
- while(i<10&&j<10){
- while(p!=NULL){
- a[i++]=p->val;//把桶中的数据放回到数组中
- f=p;p=p->next;
- delete(f);//释放空间
- }
- b[j].next=NULL;//当前桶已经查找完毕,清空,为下次存储作准备
- p=b[++j].next;//查找下一个桶
- }
- }
- int main(){
- //数据准备(做菜:源料)
- int a[10]={10000,2,3,10,1,60,7,0,9,0};
- int k=5;//k表示数组中最大数的位数,这里的5表示10000的位数
- //排序:从右到左,按LSD的方式(做菜:烹饪)
- for(int i=0;i<k;i++){
- basesort(a,i);
- }
- //output(做菜:出菜)
- for(int i=0;i<10;i++)
- printf("%d ",a[i]);
- return 0;
- }