算法-桶排序(Bucket sort)

本文由@呆代待殆原创,转载请注明出处。

 

简介:这个排序算法不属于比较排序,在平均情况下他的时间代价是O(n),并且它假设它的输入数据均匀的分布在一个固定的区间里。

 

思路:桶排序假设他的输入均匀的分布在一个固定的区间,并且它将这个区间划分成均匀的子区间,每个子区间称为一个桶,然后将输入的数据分别放到对应的桶里,再对每个桶中的数据进行单独的排序(或者对每个单独的桶再进行桶排序的递归调用,直到任何桶都只有一个数据),然后遍历输出每个桶里的数据就是最后的排序结果。

 

算法分析

平均时间复杂度:Θ(n)

空间复杂度:O(n+m) n是输入数据量,m是桶的数量

稳定性:稳定算法

是否是原址排序:否

 

代码实现

关于桶排序的实现,我们要解决两个问题

1,确定桶的数量,并把数据放到对应的桶里。

2,对每个桶里的数据进行排序。

对于问题一,我们假设我们的输入是[0,max]范围内的数,max需要当做参数输入,并规定我们的算法再任何情况下都用10个桶实现。那么我们确定数据的属于哪个桶时的算法如下

1 int putAt(int n,int max){
2     int i = 0;
3     while (i < 9){
4         if (n > max*i / 10 && n < max*(i + 1) / 10)//将0~max划分成10个区间,把数放到这些对应的区间里,区间号就是桶的编号
5             return i;
6         ++i;
7     }
8     return i;
9 }

 

对于问题二,我们采用插入排序分别对每个桶进行排序,这里给出代码,插入排序介绍传送门

 1 void insert_sort(vector<int>& v){
 2     int temp;
 3     for (int i = 1; i < v.size(); ++i){//从第二个数据开始
 4         temp = v[i];//在数组中挖一个坑,将坑里的数据放在temp中
 5         int j = i - 1;
 6         while (j>0 && temp < v[j]){//依次和坑前的数据对比,把所有比temp大的数往右挪一位(就像刚刚挖出来的坑一直在往左移动一样),直到遇到第一个比temp小的数,把temp放在这个数的右边
 7             v[j + 1] = v[j];
 8             --j;
 9         }
10         v[j + 1] = temp;//安放temp
11     }
12 }

 

下面给出桶排序的最终代码

 1 void bucket_sort(vector<int>& v,int max){
 2     vector<vector<int>> bucket;
 3     bucket.resize(10);//默认有10个桶
 4     for (const int& n : v)
 5         bucket[putAt(n,max)].push_back(n);//将数放在对应的桶里用putAt()方法确定对应的桶
 6     for (auto& n : bucket)
 7         insert_sort(n);//用插入排序排列每个桶里的元素
 8     int num = 0;
 9     for (const auto& i : bucket)//加强for中要改变被遍历的容器,必须用&修饰变量
10         for (const auto& j : i)
11             v[num++] = j;//遍历桶中的数据,依次放回原容器中
12 }

 

 

参考资料:《算法导论 中文版》(英文版第三版)(美)ThomasH.Cormen,CharlesE.Leiserson,RonaldL.Rivest,CliffordStein 著;王刚,邹恒明,殷建平,王宏志等译

posted @ 2016-04-25 13:55  呆代待殆  阅读(1096)  评论(0编辑  收藏  举报