桶排序(Bucket Sort)是对基数排序的一个变种。在排序过程中没有用到计数数组,而是用不同的桶来暂时存储关键字。看一个示意图:
排序序列 123 234 45 111 6 128
整个过程就是在不断地分配、收集。并且每一个桶都是队列,所以收集的时候得按先进先出的原则,且从第0个桶开始收集。
在实际应用中,根据桶的创建策略,桶排序也有不同的写法。下面给出两种不同的桶创建方式。一、使用静态队列创建桶。二、使用二维数组模拟桶。
#include<iostream> #include<iomanip> using namespace std; //记录类型 typedef struct record { int key; int next; }Record; //静态队列 typedef struct queue { //队头 int head; //队尾 int tail; }StaticQueue; //获取最大位数 int get_max_digit(int array[], int n) { int digit, max; digit = 0; max = array[0]; for (int i = 1; i < n; i++) { if (array[i] > max) max = array[i]; } while (max) { digit++; max /= 10; } return digit; } /* 收集 把10个桶连接起来 */ void collect(Record rec[], StaticQueue queue[], int& first) { //k是桶号 int tail, k = 0; //先找到第一个非空的桶 while (queue[k].head == -1) k++; //用first记录第一个记录的位置,为下次分配使用 first = queue[k].head; tail = queue[k].tail; while (k < 9) { k++; while (k < 9 && queue[k].head == -1) k++; //把上一个桶的尾部和当前桶的头部连接起来 if (queue[k].head != -1) { rec[tail].next = queue[k].head; tail = queue[k].tail; } } rec[tail].next = -1; } /* 分配 把n个记录分配到10个桶中 r:从右数按第r位排序(r=1,2...) first:第一个记录的下标 */ void distribute(Record rec[], int r, int first, StaticQueue queue[]) { //先把队列初始化 int i, d, cur = first; for (i = 0; i < 10; i++) queue[i].head = -1; i = d = 1; while (i < r) { i++; d *= 10; } int k; //把记录分配每一个桶中 while (cur != -1) { k = (rec[cur].key / d) % 10; //桶空,则当前记录是第一个 if (queue[k].head == -1) queue[k].head = cur; else//桶非空,则当前记录连接到尾部 rec[queue[k].tail].next = cur; //修改队列尾部,这一句不可忘了 queue[k].tail = cur; //继续给下一个记录分桶 cur = rec[cur].next; } } /* 重排 first:第一个记录的下标 */ void arrange(Record rec[], int n, int first) { int i, j = first; Record temp; for (i = 0; i < n - 1; i++) { temp = rec[j]; rec[j] = rec[i]; rec[i] = temp; rec[i].next = j; j = temp.next; while (j <= i) j = rec[j].next; } } /* 基数排序 array:待排序序列 n:序列大小 */ void RadixSort(int array[], int n) { //对排序序列进行封装 int i; Record *rec = new Record[n]; for (i = 0; i < n; i++) { rec[i].key = array[i]; rec[i].next = i + 1; } rec[n - 1].next = -1; /* 创建静态队列,每一个队列相当于一个桶 对于十进制数,只需10个桶即可 */ StaticQueue queue[10]; //获取最大排序位数 int digit = get_max_digit(array, n); int first = 0; for (i = 1; i <= digit; i++) { distribute(rec, i, first, queue); collect(rec, queue, first); } //重排 arrange(rec, n, first); //回放 for (i = 0; i < n; i++) array[i] = rec[i].key; //释放空间 delete[]rec; } //打印 void print(int array[], int n) { for (int i = 0; i < n; i++) cout << setw(6) << array[i]; cout << endl; } int main() { cout << "******桶排序(静态队列)***by David***" << endl; int array[] = { 123, 234, 45, 111, 6, 128 }; int n = sizeof(array) / sizeof(int); cout << "原序列" << endl; print(array, n); cout << "桶排序" << endl; RadixSort(array, n); print(array, n); system("pause"); return 0; }
代码下载:桶排序(静态队列)
#include<iostream> #include<iomanip> using namespace std; //最大排序个数 const int N = 12; //分配 void distribute(int array[], int n, int bucket[][N+1], int r) { int i; //对桶进行初始化,bucket[i][0]存放的是第i个桶中元素个数 for (i = 0; i < 10; i++) bucket[i][0] = 0; int d; i = d = 1; while (i < r) { d *= 10; i++; } int k; for (i = 0; i < n; i++) { k = (array[i] / d) % 10; bucket[k][0]++; bucket[k][bucket[k][0]] = array[i]; } } //收集 void collect(int array[], int n, int bucket[][N+1]) { int i, j, index; index = 0; for (i = 0; i < 10; i++) for (j = 1; j <= bucket[i][0]; j++) array[index++] = bucket[i][j]; } //获取最大位数 int get_max_digit(int array[], int n) { int digit, max; digit = 0; max = array[0]; for (int i = 1; i < n; i++) { if (array[i] > max) max = array[i]; } while (max) { digit++; max /= 10; } return digit; } //桶排序 void BucketSort(int array[], int n) { int digit = get_max_digit(array, n); int i; int bucket[10][N+1]; for (i = 1; i <= digit; i++) { //分配 distribute(array, n, bucket, i); //收集 collect(array, n, bucket); } } //打印 void print(int *a, int n) { for (int i = 0; i < n; i++) cout << setw(6) << a[i]; cout << endl; } int main() { cout << "******桶排序(二维数组)***by David***" << endl; int array[] = { 123, 234, 45, 111, 6, 128 }; int n = sizeof(array) / sizeof(int); cout << "原序列" << endl; print(array, n); cout << "桶排序" << endl; BucketSort(array, n); print(array, n); system("pause"); return 0; }
代码下载:桶排序(二维数组)
上面的两种方式都是桶排序的具体实现,总体上是分配和收集的过程。不过细节很多,需要仔细看代码。
转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/37668921
若有所帮助,顶一个哦!
专栏目录: