数据结构与算法 - 桶排序
桶排序
桶排序可以看成是计数排序的升级版,它将要排的数据分到多个有序的桶里,每个桶里的数据再单独排序,再把每个桶的数据依次取出,即可完成排序。
我们拿一组计数排序啃不掉的数据 [ 500,6123,1700,10,9999 ]
来举例。
第一步,我们创建 10 个桶,分别来装 0-1000 、1000-2000 、 2000-3000 、 3000-4000 、 4000-5000 、5000-6000、 6000-7000 、7000-8000 、8000-9000 区间的数据。
第二步,遍历原数组,对号入桶。
第三步,对桶中的数据进行单独排序,只有第一个桶中的数量大于 1 ,显然只需要排第一个桶。
最后,依次将桶中的数据取出,排序完成。
代码实现
这个桶排序乍一看好像挺简单的,但是要敲代码就需要考虑几个问题了。
桶这个东西怎么表示?
怎么确定桶的数量?
桶内排序用什么方法排?
代码如下:
void sort(vector<int>& arr) {
int max = arr[0];
int min = arr[0];
int length = arr.size();
for(int i = 1; i < length; i++) {
if(arr[i] > max) {
max = arr[i];
} else if(arr[i] < min) {
min = arr[i];
}
}
int diff = max - min;
// 桶列表
vector<vector<int>> bucketList(length);
// 每个桶的存数区间
float section = (float)diff / (float)(leng -1);
// 数据入桶
for(int i = 0; i < length; i++) {
// 当前数除以区间得出放桶的位置,减1后得出桶的下标
int num = (int)(arr[i]/section) - 1;
if(num < 0) {
num = 0;
}
bucketList[num].push_back(arr[i]);
}
// 桶内排序
for(int i = 0; i < bucketList.size(); i++) {
sort(bucketList[i].begin(), bucketList[i].end());
}
// 写入原数组
int index = 0;
for(vector<int> &arrList : bucketList) {
for(int value: arrList) {
arr[index] = value;
index++;
}
}
}
桶的数量我认为设置为原数组的长度是合理的,因为理想情况下每个数据装一个桶。
数据入桶的映射算法其实是一个开放性问题,我承认我这里写的方案并不佳,因为我测试过不同的数据集合来排序,如果你有什么更好的方案或想法,欢迎留言讨论。
桶内排序为了方便起见使用了当前语言提供的排序方法,如果对于稳定排序有所要求,可以选择使用自定义的排序算法。
桶排序的思考及其应用
在额外空间充足的情况下,尽量增大桶的数量,极限情况下每个桶只有一个数据时,或者是每只桶只装一个值时,完全避开了桶内排序的操作,桶排序的最好时间复杂度就能够达到 O(n)。
比如高考总分 750 分,全国几百万人,我们只需要创建 751 个桶,循环一遍挨个扔进去,排序速度是毫秒级。
但是如果数据经过桶的划分之后,桶与桶的数据分布极不均匀,有些数据非常多,有些数据非常少,比如[ 8,2,9,10,1,23,53,22,12,9000 ]
这十个数据,我们分成十个桶装,结果发现第一个桶装了 9 个数据,这是非常影响效率的情况,会使时间复杂度下降到
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具