基数排序(桶排序) 不同方法

Posted congmingyige

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基数排序(桶排序) 不同方法相关的知识,希望对你有一定的参考价值。

详细解释:算法导论/数据结构书

1.链式基数排序


//n个数,每个数有g个关键字
//排序:从最后的关键字开始到最前的关键字
//分配+收集
//每个关键字分配+收集需要n+n时间,而共有g个关键字,时间复杂度为O(2ng),效率很高。
//如果用数组,数据集中在一个区间,则区间的长度很长,另外的区间的内存浪费了。
//用链表可以解决这个问题,且数据不需要先后顺序,所以无必要非要用数组

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //个数
  4 #define maxn 1000
  5 //数的范围 x~y
  6 #define x 0
  7 #define y 9
  8 //关键字个数
  9 #define g 3
 10 
 11 //n个数,每个数有g个关键字
 12 //排序:从最后的关键字开始到最前的关键字
 13 //分配+收集
 14 //每个关键字分配+收集需要n+n时间,而共有g个关键字,时间复杂度为O(2ng),效率很高。
 15 //如果用数组,数据集中在一个区间,则区间的长度很长,另外的区间的内存浪费了。
 16 //用链表可以解决这个问题,且数据不需要先后顺序,所以无必要非要用数组
 17 
 18 struct node
 19 {
 20     //关键字的值
 21     long key[g+1];
 22 }data[maxn+1];
 23 //next:下一个数的编号
 24 //front,rear:一个链表的首,尾数据的编号
 25 long next[maxn+1],front[y-x+1],rear[y-x+1];
 26 
 27 int main()
 28 {
 29     long n,i,j,head,pos,value,t;
 30     scanf("%ld",&n);
 31     for (i=1;i<=n;i++)
 32         for (j=1;j<=g;j++)
 33             scanf("%ld",&data[i].key[j]);
 34     for (i=1;i<n;i++)
 35         next[i]=i+1;
 36     next[n]=0;
 37     head=1;
 38     //key i
 39     for (i=g;i>=1;i--)
 40     {
 41         //值为j的链表的首地址,0代表j链表没有元素
 42         for (j=x;j<=y;j++)
 43             front[j]=0;
 44         pos=head;
 45         ///分配
 46         while (pos)
 47         {
 48             //把一个数添加到value链表的末尾
 49             value=data[pos].key[i];
 50             //如果原来value链表有元素,则原来value链表的末尾元素的后继为第pos个数
 51             //如果原来value链表没有元素,则value链表的起始元素为第pos个数
 52             if (front[value]!=0)
 53                 next[rear[value]]=pos;
 54             else
 55                 front[value]=pos;
 56             //当前value链表的末尾元素为第pos个数
 57             rear[value]=pos;
 58             pos=next[pos];
 59         }
 60         ///收集
 61         //把x链表,x+1链表,……,y链表 连接起来,而k链表的最后一个元素的后继为k+1链表的第一个元素
 62         value=x;
 63         while (front[value]==0)
 64             value++;
 65         head=front[value];
 66         while (value<=y)
 67         {
 68             t=value+1;
 69             while (front[t]==0 && t<=y)
 70                 t++;
 71             if (t==y+1)
 72                 break;
 73             next[rear[value]]=front[t];
 74             value=t;
 75         }
 76         next[rear[value]]=0;
 77     }
 78     printf("\n");
 79     pos=head;
 80     while (pos)
 81     {
 82         for (i=1;i<=g;i++)
 83             printf("%ld ",data[pos].key[i]);
 84         printf("\n");
 85         pos=next[pos];
 86     }
 87     return 0;
 88 }
 89 /*
 90 input:
 91 10
 92 1 1 2
 93 9 7 9
 94 3 8 5
 95 1 3 3
 96 5 4 3
 97 6 8 5
 98 2 1 3
 99 1 4 5
100 9 1 1
101 5 1 3
102 output:
103 1 1 2
104 1 3 3
105 1 4 5
106 2 1 3
107 3 8 5
108 5 1 3
109 5 4 3
110 6 8 5
111 9 1 1
112 9 7 9
113 */

 

2.基数排序+排序

 

//n个数,每个数有g个关键字
//可以在一次基数排序(桶排序)后,结合其它排序
//适用于:2~3个关键字,第一个关键字的范围较大,且分布较为分散,
    //通过第一个关键字把数分成若干个区间后,区间的大小较小,从而每个区间的排序时间也较小

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //个数
  4 #define maxn 1000
  5 //数的范围 x~y
  6 #define x 0
  7 #define y 9
  8 //关键字个数
  9 #define g 3
 10 
 11 //n个数,每个数有g个关键字
 12 //可以在一次基数排序(桶排序)后,结合其它排序
 13 //适用于:2~3个关键字,第一个关键字的范围较大,且分布较为分散,
 14     //通过第一个关键字把数分成若干个区间后,区间的大小较小,从而每个区间的排序时间也较小
 15 
 16 struct node
 17 {
 18     //关键字的值
 19     long key[g+1];
 20 }data[maxn+1],f[maxn+1];
 21 //next:下一个数的编号
 22 //front,rear:一个链表的首,尾数据的编号
 23 long next[maxn+1],front[y-x+1],rear[y-x+1];
 24 
 25 void qsort_(long l,long r)
 26 {
 27     long i,j,p,q;
 28     struct node t;
 29     i=l; j=r; p=f[(l+r)>>1].key[2]; q=f[(l+r)>>1].key[3];
 30     while (i<=j)
 31     {
 32         while (f[i].key[2]<p || (f[i].key[2]==p && f[i].key[3]<q)) i++;
 33         while (f[j].key[2]>p || (f[j].key[2]==p && f[j].key[3]>q)) j--;
 34         if (i<=j)
 35         {
 36             t=f[i];
 37             f[i]=f[j];
 38             f[j]=t;
 39             i++;
 40             j--;
 41         }
 42     }
 43     if (i<r) qsort_(i,r);
 44     if (j>l) qsort_(l,j);
 45 }
 46 
 47 int main()
 48 {
 49     long n,i,j,head,pos,value,b;
 50     scanf("%ld",&n);
 51     for (i=1;i<=n;i++)
 52         for (j=1;j<=g;j++)
 53             scanf("%ld",&data[i].key[j]);
 54     for (i=1;i<n;i++)
 55         next[i]=i+1;
 56     next[n]=0;
 57     head=1;
 58     ///key 1
 59 
 60     //值为j的链表的首地址,0代表j链表没有元素
 61     for (j=x;j<=y;j++)
 62         front[j]=0;
 63     pos=head;
 64     ///分配
 65     while (pos)
 66     {
 67         //把一个数添加到value链表的末尾
 68         value=data[pos].key[1];
 69         //如果原来value链表有元素,则原来value链表的末尾元素的后继为第pos个数
 70         //如果原来value链表没有元素,则value链表的起始元素为第pos个数
 71         if (front[value]!=0)
 72             next[rear[value]]=pos;
 73         else
 74             front[value]=pos;
 75         //当前value链表的末尾元素为第pos个数
 76         rear[value]=pos;
 77         pos=next[pos];
 78     }
 79     ///收集
 80     printf("\n");
 81     j=0;
 82     for (i=x;i<=y;i++)
 83         if (front[i]!=0)
 84         {
 85             b=j+1;
 86             pos=front[i];
 87             while (pos!=rear[i])
 88             {
 89                 j++;
 90                 f[j]=data[pos];
 91                 pos=next[pos];
 92             }
 93             j++;
 94             f[j]=data[pos];
 95             qsort_(b,j);
 96         }
 97     for (i=1;i<=n;i++)
 98     {
 99         for (j=1;j<=g;j++)
100             printf("%ld ",f[i].key[j]);
101         printf("\n");
102     }
103     return 0;
104 }
105 /*
106 input:
107 10
108 1 1 2
109 9 7 9
110 3 8 5
111 1 3 3
112 5 4 3
113 6 8 5
114 2 1 3
115 1 4 5
116 9 1 1
117 5 1 3
118 output:
119 1 1 2
120 1 3 3
121 1 4 5
122 2 1 3
123 3 8 5
124 5 1 3
125 5 4 3
126 6 8 5
127 9 1 1
128 9 7 9
129 */

 

3.从前到后依次对关键字排序(不推荐)

 

//n个数,每个数有g个关键字
//如果从最前的关键字开始到最后的关键字排序,则需要sort(p,q,w) data[x]~data[y]排第w个关键字,
    //然后延伸出sort(s,t,w+1) [p<=s<=t<=q]
//该方法耗费大量时间和内存,不推荐

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //个数
  4 #define maxn 1000
  5 //数的范围 x~y
  6 #define x 0
  7 #define y 9
  8 //关键字个数
  9 #define g 3
 10 
 11 //n个数,每个数有g个关键字
 12 //如果从最前的关键字开始到最后的关键字排序,则需要sort(p,q,w) data[x]~data[y]排第w个关键字,
 13     //然后延伸出sort(s,t,w+1) [p<=s<=t<=q]
 14 //该方法耗费大量时间和内存,不推荐
 15 
 16 struct node
 17 {
 18     //关键字的值
 19     long key[g+1];
 20 }data[maxn+1],f[maxn+1];
 21 //next:下一个数的编号
 22 //front,rear:一个链表的首,尾数据的编号
 23 
 24 void sort(long p,long q,long w)
 25 {
 26     long i,j,head,pos,value,next[maxn+1],front[y-x+1],rear[y-x+1],b[y+1],e[y+1];
 27     for (i=p;i<q;i++)
 28         next[i]=i+1;
 29     next[q]=0;
 30     head=p;
 31     //值为j的链表的首地址,0代表j链表没有元素
 32     for (j=x;j<=y;j++)
 33         front[j]=0;
 34     pos=head;
 35     ///分配
 36     while (pos)
 37     {
 38         //把一个数添加到value链表的末尾
 39         value=data[pos].key[w];
 40         //如果原来value链表有元素,则原来value链表的末尾元素的后继为第pos个数
 41         //如果原来value链表没有元素,则value链表的起始元素为第pos个数
 42         if (front[value]!=0)
 43             next[rear[value]]=pos;
 44         else
 45             front[value]=pos;
 46         //当前value链表的末尾元素为第pos个数
 47         rear[value]=pos;
 48         pos=next[pos];
 49     }
 50     ///收集
 51     for (i=p;i<=q;i++)
 52         f[i]=data[i];
 53     j=p-1;
 54     for (i=x;i<=y;i++)
 55         if (front[i]!=0)
 56         {
 57             b[i]=j+1;
 58             pos=front[i];
 59             while (pos!=rear[i])
 60             {
 61                 j++;
 62                 data[j]=f[pos];
 63                 pos=next[pos];
 64             }
 65             j++;
 66             data[j]=f[pos];
 67             e[i]=j;
 68         }
 69     if (w!=g)
 70     {
 71         for (i=x;i<=y;i++)
 72             //没有数或者只有1个数就不用排了
 73             if (front[i]!=0 && b[i]!=e[i])
 74                 sort(b[i],e[i],w+1);
 75     }
 76 }
 77 
 78 int main()
 79 {
 80     long i,j,n;
 81     scanf("%ld",&n);
 82     for (i=1;i<=n;i++)
 83         for (j=1;j<=g;j++)
 84             scanf("%ld",&data[i].key[j]);
 85     sort(1,n,1);
 86     printf("\n");
 87     for (i=1;i<=n;i++)
 88     {
 89         for (j=1;j<=g;j++)
 90             printf("%ld ",data[i].key[j]);
 91         printf("\n");
 92     }
 93     return 0;
 94 }
 95 /*
 96 input:
 97 10
 98 1 1 2
 99 9 7 9
100 3 8 5
101 1 3 3
102 5 4 3
103 6 8 5
104 2 1 3
105 1 4 5
106 9 1 1
107 5 1 3
108 output:
109 1 1 2
110 1 3 3
111 1 4 5
112 2 1 3
113 3 8 5
114 5 1 3
115 5 4 3
116 6 8 5
117 9 1 1
118 9 7 9
119 */

 

题目:

题目13基数排序的实现(学时:3)
A为每个关键字不超过3位的十进制整数关键字集合,试编写一个采用静态链表组织模式实现的基数排序程序将A进行由小到大的排序。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //个数
  4 #define maxn 1000
  5 //数的范围 x~y
  6 #define x 0
  7 #define y 9
  8 //关键字个数
  9 #define g 3
 10 
 11 //n个数,每个数有g个关键字
 12 //排序:从最后的关键字开始到最前的关键字
 13 //分配+收集
 14 //每个关键字分配+收集需要n+n时间,而共有g个关键字,时间复杂度为O(2ng)。
 15 //如果用数组,数据集中在一个区间,则区间的长度很长,另外的区间的内存浪费了。
 16 //用链表可以解决这个问题,且数据不需要先后顺序,所以无必要非要用数组
 17 
 18 struct node
 19 {
 20     //关键字的值
 21     long key[g+1];
 22 }data[maxn+1];
 23 //next:下一个数的编号
 24 //front,rear:一个链表的首,尾数据的编号
 25 long next[maxn+1],front[y-x+1],rear[y-x+1];
 26 
 27 int main()
 28 {
 29     char c;
 30     long n,i,j,head,pos,value,t;
 31     scanf("%ld",&n);
 32     for (i=1;i<=n;i++)
 33     {
 34         c=getchar();
 35         for (j=1;j<=g;j++)
 36         {
 37             c=getchar();
 38             data[i].key[j]=c-48;
 39         }
 40 
 41     }
 42     for (i=1;i<n;i++)
 43         next[i]=i+1;
 44     next[n]=0;
 45     head=1;
 46     //key i
 47     for (i=g;i>=1;i--)
 48     {
 49         //值为j的链表的首地址,0代表j链表没有元素
 50         for (j=x;j<=y;j++)
 51             front[j]=0;
 52         pos=head;
 53         ///分配
 54         while (pos)
 55         {
 56             //把一个数添加到value链表的末尾
 57             value=data[pos].key[i];
 58             //如果原来value链表有元素,则原来value链表的末尾元素的后继为第pos个数
 59             //如果原来value链表没有元素,则value链表的起始元素为第pos个数
 60             if (front[value]!=0)
 61                 next[rear[value]]=pos;
 62             else
 63                 front[value]=pos;
 64             //当前value链表的末尾元素为第pos个数
 65             rear[value]=pos;
 66             pos=next[pos];
 67         }
 68         ///收集
 69         //把x链表,x+1链表,……,y链表 连接起来,而k链表的最后一个元素的后继为k+1链表的第一个元素
 70         value=x;
 71         while (front[value]==0)
 72             value++;
 73         head=front[value];
 74         while (value<=y)
 75         {
 76             t=value+1;
 77             while (front[t]==0 && t<=y)
 78                 t++;
 79             if (t==y+1)
 80                 break;
 81             next[rear[value]]=front[t];
 82             value=t;
 83         }
 84         next[rear[value]]=0;
 85     }
 86     printf("\n");
 87     pos=head;
 88     while (pos)
 89     {
 90         for (i=1;i<=g;i++)
 91             printf("%ld",data[pos].key[i]);
 92         printf("\n");
 93         pos=next[pos];
 94     }
 95     return 0;
 96 }
 97 /*
 98 input:
 99 10
100 112
101 979
102 385
103 133
104 543
105 685
106 213
107 145
108 911
109 513
110 output:
111 112
112 133
113 145
114 213
115 385
116 513
117 543
118 685
119 911
120 979
121 */

 

以上是关于基数排序(桶排序) 不同方法的主要内容,如果未能解决你的问题,请参考以下文章

基数排序(桶排序) 不同方法

10基数排序

排序算法 (11.基数排序)

常用排序算法基数排序桶排序以及计数排序

吴裕雄--天生自然数据结构:十大经典排序算法——基数排序

基数排序的具体实现及其原理