一. 算法描述
平均时间复杂度:O(dn)(d即表示整形的最高位数)
空间复杂度:O(10n) (10表示0~9,用于存储临时的序列)
稳定性:稳定
三. 算法实现
- /********************************************************
- *函数名称:GetNumInPos
- *参数说明:num 一个整形数据
- * pos 表示要获得的整形的第pos位数据
- *说明: 找到num的从低到高的第pos位的数据
- *********************************************************/
- int GetNumInPos(int num,int pos)
- {
- int temp = 1;
- for (int i = 0; i < pos - 1; i++)
- temp *= 10;
- return (num / temp) % 10;
- }
- /********************************************************
- *函数名称:RadixSort
- *参数说明:pDataArray 无序数组;
- * iDataNum为无序数据个数
- *说明: 基数排序
- *********************************************************/
- #define RADIX_10 10 //整形排序
- #define KEYNUM_31 31 //关键字个数,这里为整形位数
- void RadixSort(int* pDataArray, int iDataNum)
- {
- int *radixArrays[RADIX_10]; //分别为0~9的序列空间
- for (int i = 0; i < 10; i++)
- {
- radixArrays[i] = (int *)malloc(sizeof(int) * (iDataNum + 1));
- radixArrays[i][0] = 0; //index为0处记录这组数据的个数
- }
- for (int pos = 1; pos <= KEYNUM_31; pos++) //从个位开始到31位
- {
- for (int i = 0; i < iDataNum; i++) //分配过程
- {
- int num = GetNumInPos(pDataArray[i], pos);
- int index = ++radixArrays[num][0];
- radixArrays[num][index] = pDataArray[i];
- }
- for (int i = 0, j =0; i < RADIX_10; i++) //收集
- {
- for (int k = 1; k <= radixArrays[i][0]; k++)
- pDataArray[j++] = radixArrays[i][k];
- radixArrays[i][0] = 0; //复位
- }
- }
- }
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将阵列分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的阵列内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
例如要对大小为[1..1000]范围内的n个整数A[1..n]排序,可以把桶设为大小为10的范围,具体而言,设集合B[1]存储[1..10]的整数,集合B[2]存储(10..20]的整数,……集合B[i]存储((i-1)*10, i*10]的整数,i = 1,2,..100。总共有100个桶。然后对A[1..n]从头到尾扫描一遍,把每个A[i]放入对应的桶B[j]中。 然后再对这100个桶中每个桶里的数字排序,这时可用冒泡,选择,乃至快排,一般来说任何排序法都可以。最后依次输出每个桶里面的数字,且每个桶中的数字从小到大输出,这样就得到所有数字排好序的一个序列了。
假设有n个数字,有m个桶,如果数字是平均分布的,则每个桶里面平均有n/m个数字。如果对每个桶中的数字采用快速排序,那么整个算法的复杂度是O(n+m*n/m*log(n/m))=O(n+nlogn-nlogm)
从上式看出,当m接近n的时候,桶排序复杂度接近O(n)
当然,以上复杂度的计算是基于输入的n个数字是平均分布这个假设的。这个假设是很强的,实际应用中效果并没有这么好。如果所有的数字都落在同一个桶中,那就退化成一般的排序了。
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- extern void quick_sort(int a[], int p, int q);/* not necessary */
- struct barrel {
- int node[10];
- int count;/* the num of node */
- };
- void bucket_sort(int data[], int size)
- {
- int max, min, num, pos;
- int i, j, k;
- struct barrel *pBarrel;
- max = min = data[0];
- for (i = 1; i < size; i++) {
- if (data[i] > max) {
- max = data[i];
- } else if (data[i] < min) {
- min = data[i];
- }
- }
- num = (max - min + 1) / 10 + 1;
- pBarrel = (struct barrel*)malloc(sizeof(struct barrel) * num);
- memset(pBarrel, 0, sizeof(struct barrel) * num);
- /* put data[i] into barrel which it belong to */
- for (i = 0; i < size; i++) {
- k = (data[i] - min + 1) / 10;/* calculate the index of data[i] in barrel */
- (pBarrel + k)->node[(pBarrel + k)->count] = data[i];
- (pBarrel + k)->count++;
- }
- pos = 0;
- for (i = 0; i < num; i++) {
- quick_sort((pBarrel+i)->node, 0, (pBarrel+i)->count);/* sort node in every barrel */
- for (j = 0; j < (pBarrel+i)->count; j++) {
- data[pos++] = (pBarrel+i)->node[j];
- }
- }
- free(pBarrel);
- }
- main()
- {
- int data[] = {78, 17, 39, 26, 72, 94, 21, 12, 23, 91}, i;
- int size = sizeof(data) / sizeof(int);
- bucket_sort(data, size);
- for (i = 0; i < size; i++)
- printf("%d ", data[i]);
- }
- C++
-
#include <iostream> #include <cstdlib> #include <cstring> using namespace std; struct barrel { int node[30]; //设桶中最多元素的上限 int count; //桶中的真实元素的个数 }; int comp(const void *a,const void *b) { return *(int *)a-*(int *)b; } class bucket_sort { public: bucket_sort(); // 用于初始化数据 ~bucket_sort(){}; void BucketSort(); void Output(); void SetNumsOfBucket(int numsOfBucket) { Buckets = numsOfBucket; } private: int length; int *data; struct Node **head; int Buckets; }; void bucket_sort::BucketSort() { int dataMax, dataMin, numsOfBucket; dataMax = dataMin = data[0]; for(int i = 0; i < length; i++) { if(dataMax < data[i]) dataMax = data[i]; if(dataMin > data[i]) dataMin = data[i]; } numsOfBucket = (dataMax - dataMin + 1)/10 + 1; // 桶的个数 SetNumsOfBucket(numsOfBucket); struct barrel *pBarrel = new struct barrel[numsOfBucket]; memset(pBarrel, 0, sizeof(struct barrel) * numsOfBucket); for (int i = 0; i < length; i++) { int k = (data[i] - dataMin + 1)/10; (pBarrel + k)->node[(pBarrel + k)->count] = data[i]; (pBarrel + k)->count++; } int pos_tmp = 0; for (int i = 0; i < numsOfBucket; i++) { qsort((pBarrel + i)->node, (pBarrel + i)->count, sizeof(int), comp); for (int j = 0; j < (pBarrel + i)->count; j++) data[pos_tmp++] = (pBarrel + i)->node[j]; } delete [] pBarrel; } bucket_sort::bucket_sort() { cout << "输入原始数据的个数: " ; cin >> length; data = new int[length]; cout << "输入数据:"<<endl; for (int i = 0; i < length; i++) cin >> data[i]; } void bucket_sort::Output() { cout << "数据为: "; for (int i = 0; i < length; i++) cout << data[i] << " "; cout << endl; } void main() { bucket_sort Test; Test.Output(); Test.BucketSort(); Test.Output(); }