1. 程式人生 > >基數排序(桶排序) 不同方法

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

區間 col 一個 fin 收集 truct ext data har

詳細解釋:算法導論/數據結構書

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 */

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