(1.3.6.2)线性排序:桶排序

桶排序

桶排序(Bucket Sort)是对基数排序的一个变种。在排序过程中没有用到计数数组,而是用不同的桶来暂时存储关键字。看一个示意图:

排序序列 123 234 45 111 6 128

(1.3.6.2)线性排序:桶排序_第1张图片

整个过程就是在不断地分配、收集。并且每一个桶都是队列,所以收集的时候得按先进先出的原则,且从第0个桶开始收集。

在实际应用中,根据桶的创建策略,桶排序也有不同的写法。下面给出两种不同的桶创建方式。一、使用静态队列创建桶。二、使用二维数组模拟桶。

静态队列桶

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. using namespace std;  
  4. //记录类型  
  5. typedef struct record  
  6. {  
  7.     int key;  
  8.     int next;  
  9. }Record;  
  10. //静态队列  
  11. typedef struct queue  
  12. {  
  13.     //队头  
  14.     int head;  
  15.     //队尾  
  16.     int tail;  
  17. }StaticQueue;  
  18. //获取最大位数  
  19. int get_max_digit(int array[], int n)  
  20. {  
  21.     int digit, max;  
  22.     digit = 0;  
  23.     max = array[0];  
  24.     for (int i = 1; i < n; i++)  
  25.     {  
  26.         if (array[i] > max)  
  27.             max = array[i];  
  28.     }  
  29.     while (max)  
  30.     {  
  31.         digit++;  
  32.         max /= 10;  
  33.     }  
  34.     return digit;  
  35. }  
  36.   
  37. /* 
  38. 收集 
  39. 把10个桶连接起来 
  40. */  
  41. void collect(Record rec[], StaticQueue queue[], int& first)  
  42. {  
  43.     //k是桶号  
  44.     int tail, k = 0;  
  45.     //先找到第一个非空的桶  
  46.     while (queue[k].head == -1)  
  47.         k++;  
  48.     //用first记录第一个记录的位置,为下次分配使用  
  49.     first = queue[k].head;  
  50.     tail = queue[k].tail;  
  51.     while (k < 9)  
  52.     {  
  53.         k++;  
  54.         while (k < 9 && queue[k].head == -1)  
  55.             k++;  
  56.         //把上一个桶的尾部和当前桶的头部连接起来  
  57.         if (queue[k].head != -1)  
  58.         {  
  59.             rec[tail].next = queue[k].head;  
  60.             tail = queue[k].tail;  
  61.         }  
  62.     }  
  63.     rec[tail].next = -1;  
  64. }  
  65.   
  66. /* 
  67. 分配 
  68. 把n个记录分配到10个桶中 
  69. r:从右数按第r位排序(r=1,2...) 
  70. first:第一个记录的下标 
  71. */  
  72. void distribute(Record rec[], int r, int first, StaticQueue queue[])  
  73. {  
  74.     //先把队列初始化  
  75.     int i, d, cur = first;  
  76.     for (i = 0; i < 10; i++)  
  77.         queue[i].head = -1;  
  78.   
  79.     i =  d = 1;  
  80.     while (i < r)  
  81.     {  
  82.         i++;  
  83.         d *= 10;  
  84.     }  
  85.     int k;  
  86.     //把记录分配每一个桶中  
  87.     while (cur != -1)  
  88.     {  
  89.         k = (rec[cur].key / d) % 10;  
  90.         //桶空,则当前记录是第一个  
  91.         if (queue[k].head == -1)  
  92.             queue[k].head = cur;  
  93.         else//桶非空,则当前记录连接到尾部  
  94.             rec[queue[k].tail].next = cur;  
  95.         //修改队列尾部,这一句不可忘了  
  96.         queue[k].tail = cur;  
  97.         //继续给下一个记录分桶  
  98.         cur = rec[cur].next;  
  99.     }  
  100. }  
  101.   
  102. /* 
  103. 重排 
  104. first:第一个记录的下标 
  105. */  
  106. void arrange(Record rec[], int n, int first)  
  107. {  
  108.     int i, j = first;  
  109.     Record temp;  
  110.     for (i = 0; i < n - 1; i++)  
  111.     {  
  112.         temp = rec[j];  
  113.         rec[j] = rec[i];  
  114.         rec[i] = temp;  
  115.         rec[i].next = j;  
  116.         j = temp.next;  
  117.         while (j <= i)  
  118.             j = rec[j].next;  
  119.     }  
  120. }  
  121.   
  122. /* 
  123. 基数排序 
  124. array:待排序序列 
  125. n:序列大小 
  126. */  
  127. void RadixSort(int array[], int n)  
  128. {  
  129.     //对排序序列进行封装  
  130.     int i;  
  131.     Record *rec = new Record[n];  
  132.     for (i = 0; i < n; i++)  
  133.     {  
  134.         rec[i].key = array[i];  
  135.         rec[i].next = i + 1;  
  136.     }  
  137.     rec[n - 1].next = -1;  
  138.     /* 
  139.     创建静态队列,每一个队列相当于一个桶 
  140.     对于十进制数,只需10个桶即可 
  141.     */  
  142.     StaticQueue queue[10];  
  143.     //获取最大排序位数  
  144.     int digit = get_max_digit(array, n);  
  145.     int first = 0;  
  146.     for (i = 1; i <= digit; i++)  
  147.     {  
  148.         distribute(rec, i, first, queue);  
  149.         collect(rec, queue, first);  
  150.     }  
  151.     //重排  
  152.     arrange(rec, n, first);  
  153.     //回放  
  154.     for (i = 0; i < n; i++)  
  155.         array[i] = rec[i].key;  
  156.     //释放空间  
  157.     delete[]rec;  
  158. }  
  159.   
  160. //打印  
  161. void print(int array[], int n)  
  162. {  
  163.     for (int i = 0; i < n; i++)  
  164.         cout << setw(6) << array[i];  
  165.     cout << endl;  
  166. }  
  167.   
  168. int main()  
  169. {  
  170.     cout << "******桶排序(静态队列)***by David***" << endl;  
  171.     int array[] = { 123, 234, 45, 111, 6, 128 };  
  172.     int n = sizeof(array) / sizeof(int);  
  173.     cout << "原序列" << endl;  
  174.     print(array, n);  
  175.     cout << "桶排序" << endl;  
  176.     RadixSort(array, n);  
  177.     print(array, n);  
  178.     system("pause");  
  179.     return 0;  
  180. }  

运行

(1.3.6.2)线性排序:桶排序_第2张图片


代码下载:桶排序(静态队列)

二维数组桶  

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. using namespace std;  
  4. //最大排序个数  
  5. const int N = 12;  
  6. //分配  
  7. void distribute(int array[], int n, int bucket[][N+1], int r)  
  8. {  
  9.     int i;  
  10.     //对桶进行初始化,bucket[i][0]存放的是第i个桶中元素个数  
  11.     for (i = 0; i < 10; i++)  
  12.         bucket[i][0] = 0;  
  13.     int d;  
  14.     i = d = 1;  
  15.     while (i < r)  
  16.     {  
  17.         d *= 10;  
  18.         i++;  
  19.     }  
  20.     int k;  
  21.     for (i = 0; i < n; i++)  
  22.     {  
  23.         k = (array[i] / d) % 10;  
  24.         bucket[k][0]++;  
  25.         bucket[k][bucket[k][0]] = array[i];  
  26.     }  
  27. }  
  28. //收集  
  29. void collect(int array[], int n, int bucket[][N+1])  
  30. {  
  31.     int i, j, index;  
  32.     index = 0;  
  33.     for (i = 0; i < 10; i++)  
  34.     for (j = 1; j <= bucket[i][0]; j++)  
  35.         array[index++] = bucket[i][j];  
  36. }  
  37. //获取最大位数  
  38. int get_max_digit(int array[], int n)  
  39. {  
  40.     int digit, max;  
  41.     digit = 0;  
  42.     max = array[0];  
  43.     for (int i = 1; i < n; i++)  
  44.     {  
  45.         if (array[i] > max)  
  46.             max = array[i];  
  47.     }  
  48.     while (max)  
  49.     {  
  50.         digit++;  
  51.         max /= 10;  
  52.     }  
  53.     return digit;  
  54. }  
  55. //桶排序  
  56. void BucketSort(int array[], int n)  
  57. {  
  58.     int digit = get_max_digit(array, n);  
  59.     int i;  
  60.     int bucket[10][N+1];  
  61.     for (i = 1; i <= digit; i++)  
  62.     {  
  63.         //分配  
  64.         distribute(array, n, bucket, i);  
  65.         //收集  
  66.         collect(array, n, bucket);  
  67.     }  
  68. }  
  69. //打印  
  70. void print(int *a, int n)  
  71. {  
  72.     for (int i = 0; i < n; i++)  
  73.         cout << setw(6) << a[i];  
  74.     cout << endl;  
  75. }  
  76. int main()  
  77. {  
  78.     cout << "******桶排序(二维数组)***by David***" << endl;  
  79.     int array[] = { 123, 234, 45, 111, 6, 128 };  
  80.     int n = sizeof(array) / sizeof(int);  
  81.     cout << "原序列" << endl;  
  82.     print(array, n);  
  83.     cout << "桶排序" << endl;  
  84.     BucketSort(array, n);  
  85.     print(array, n);  
  86.     system("pause");  
  87.     return 0;  
  88. }  

运行

(1.3.6.2)线性排序:桶排序_第3张图片


代码下载:桶排序(二维数组)


小结

上面的两种方式都是桶排序的具体实现,总体上是分配和收集的过程。不过细节很多,需要仔细看代码。

你可能感兴趣的:((1.3.6.2)线性排序:桶排序)