桶排序简介
-
桶排序是计数排序的升级版
- 计数排序是一一对应的映射,且只适用于整数
- 桶排序适用于分布比较均匀的集合,支持浮点数等
-
它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定
-
为了使桶排序更加高效,我们需要做到这两点:
- 在额外空间充足的情况下,尽量增大桶的数量
- 使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中
-
对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
桶排序步骤
-
将排序数组中的元素,通过映射函数,分配到有限数量的桶里
- 映射函数设计很重要,一般是 f = array[i] / k; k^2 = n; n是所有元素个数
- 所谓桶,就是一个二维的数组,第一维用来计算映射关系,第二维用来存储元素
- 如何确定桶的个数
- bucket_n:(最大值-最小值)/元素个数,对于分布均匀的元素,则映射也均匀
- 取n,使得:(bucket_n)^2 = element_N
- 如何确定桶的大小
- 对于每个桶大小,一般设置为元素个数,因为可能因为映射函数设计的不好,使得所有元素映射到同一个桶中
- 二维数组的第二维可以用vector,也可以用链表,则不需要提前限定大小
-
每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)
-
依次把各个桶中的记录列出来记得到有序序列
-
当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是比较排序,他不受到O(n log n)下限的影响。空间:O(n+k)。
桶排序实现
#include<iostream>
#include<stdlib.h>
#include<time.h>
#include<vector>
#include<algorithm>
using namespace std;
#define N 10
vector<double>v;//待排序数组
//int bucket_size = N;
int bucket_cnt = 10;//桶的个数
void bucketSort(vector<double>&v){
vector<double>buckets[bucket_cnt];//用vector实现链表
for(double val:v){
int index = val/bucket_cnt;
buckets[index].push_back(val);
}
int index = 0;
for(auto bucket:buckets){
sort(bucket.begin(),bucket.end());
for(double vv:bucket){
v[index++] = vv;
}
}
}
int main(){
srand(unsigned(time(NULL)));//用来产生每次都不同的伪随机数,以时间作为随机种子
double rand_num;
cout<<"原数组:";
for(int i = 0; i < N; i++){
rand_num = rand()/double(RAND_MAX);//(0,1)之间的浮点随机数
v.push_back(rand_num*100);//0-100的浮点随机数
cout<<v[i]<<" ";
}
bucketSort(v);
cout<<endl<<"排序后数组:";
for(double val:v)
cout<<val<<" ";
return 0;
}