基數排序(桶排序) 不同方法
阿新 • • 發佈:2017-05-07
區間 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 #definey 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 */
基數排序(桶排序) 不同方法