当前位置: 首页 > ds >正文

排序算法——桶排序

一、介绍

前述的几种排序算法都属于“基于比较的排序算法”,它们通过比较元素间的大小来实现排序。此类排序算法的时间复杂度无法超越𝑂(𝑛log𝑛)。接下来,我们将探讨几种“非比较排序算法”,它们的时间复杂度可以达到线性阶。

「桶排序bucketsort」是分治策略的一个典型应用。它通过设置一些具有大小顺序的桶,每个桶对应一个数据范围,将数据平均分配到各个桶中;然后,在每个桶内部分别执行排序;最终按照桶的顺序将所有数据合并。

二、算法流程

考虑一个长度为𝑛的数组,元素是范围[0,1)的浮点数。桶排序的流程如下所示。
1. 初始化𝑘个桶,将𝑛个元素分配到𝑘个桶中。
2. 对每个桶分别执行排序(本文采用编程语言的内置排序函数)。
3. 按照桶的从小到大的顺序,合并结果。

三、完整代码

def bucket_sort(nums: list[float]):"""桶排序"""# 初始化 k = n/2 个桶,预期向每个桶分配 2 个元素k = len(nums) // 2buckets = [[] for _ in range(k)]# 1. 将数组元素分配到各个桶中for num in nums:# 输入数据范围为 [0, 1),使用 num * k 映射到索引范围 [0, k-1]i = int(num * k)# 将 num 添加进桶 ibuckets[i].append(num)# 2. 对各个桶执行排序for bucket in buckets:# 使用内置排序函数,也可以替换成其他排序算法bucket.sort()# 3. 遍历桶合并结果i = 0for bucket in buckets:for num in bucket:nums[i] = numi += 1if __name__ == "__main__":# 设输入数据为浮点数,范围为 [0, 1)nums = [0.49, 0.96, 0.82, 0.09, 0.57, 0.43, 0.91, 0.75, 0.15, 0.37]bucket_sort(nums)print("桶排序完成后 nums =", nums)

四、算法特性

桶排序适用于处理体量很大的数据。例如,输入数据包含100万个元素,由于空间限制,系统内存无法一次性加载所有数据。此时,可以将数据分成1000个桶,然后分别对每个桶进行排序,最后将结果合并。
‧ 时间复杂度𝑂(𝑛+𝑘):假设元素在各个桶内平均分布,那么每个桶内的元素数量为𝑛/𝑘。假设排序单
个桶使用𝑂(𝑛/𝑘log(𝑛/𝑘))时间,则排序所有桶使用𝑂(𝑛log(𝑛/𝑘))时间。当桶数量𝑘比较大时,时间复杂度则趋向于𝑂(𝑛)。合并结果时需要遍历所有桶和元素,花费𝑂(𝑛+𝑘)时间。
自适应排序:在最坏情况下,所有数据被分配到一个桶中,且排序该桶使用𝑂()时间。
‧ 空间复杂度𝑂(𝑛+𝑘)、非原地排序:需要借助𝑘个桶和总共𝑛个元素的额外空间。
‧ 桶排序是否稳定取决于排序桶内元素的算法是否稳定。

五、如何实现平均分配

桶排序的时间复杂度理论上可以达到𝑂(𝑛),关键在于将元素均匀分配到各个桶中,因为实际数据往往不是均匀分布的。例如,我们想要将淘宝上的所有商品按价格范围平均分配到10个桶中,但商品价格分布不均,低于100元的非常多,高于1000元的非常少。若将价格区间平均划分为10份,各个桶中的商品数量差距会非常大。

 

为实现平均分配,我们可以先设定一个大致的分界线,将数据粗略地分到3个桶中。分配完毕后,再将商品较多的桶继续划分为3个桶,直至所有桶中的元素数量大致相等。


如图所示,这种方法本质上是创建一个递归树,目标是让叶节点的值尽可能平均。当然,不一定要每轮将数据划分为3个桶,具体划分方式可根据数据特点灵活选择。

如果我们提前知道商品价格的概率分布,则可以根据数据概率分布设置每个桶的价格分界线。值得注意的是,数据分布并不一定需要特意统计,也可以根据数据特点采用某种概率模型进行近似。
如下图所示,我们假设商品价格服从正态分布,这样就可以合理地设定价格区间,从而将商品平均分配到各个桶中。

 

 

http://www.xdnf.cn/news/4636.html

相关文章:

  • 注意力机制(Attention)
  • 【关于ESP8266下载固件库的问题】
  • C++ 析构函数
  • 【Ollama】docker离线部署Ollama+deepseek
  • 从机器人到调度平台:超低延迟RTMP|RTSP播放器系统级部署之道
  • DeepSeek 入门:从注册到首轮对话全流程
  • Mysql如何完成数据的增删改查(详解从0到1)
  • 打造个人知识库,wsl+ollama部署deepseek与vscode集成
  • NetBox Docker 全功能部署方案(Ubuntu 22.04 + Docker)
  • k8s 中 deployment 管理的多个 pod 构成集群吗
  • PostgreSQL 查询历史最大进程数方法
  • 商汤科技前端面试题及参考答案
  • 服务器上机用到的设备
  • .net在DB First模式使用pgsql
  • K8s节点宕机自愈全流程解析
  • 【数据结构入门训练DAY-28】蓝桥杯算法提高VIP-产生数
  • 【前端基础】7、CSS的字体属性(font相关)
  • React Router Vs Vue Router
  • AGV智能搬运机器人:富唯智能引领工业物流高效变革
  • DeepSeek架构解析:从神经动力学视角解构万亿参数模型的认知涌现机制
  • 企业该如何选择合适的DDOS防护?
  • C++代码随想录刷题知识分享-----判断两个字符串是否为字母异位词(Anagram)【LeetCode 242】
  • 【论文阅读】Reconstructive Neuron Pruning for Backdoor Defense
  • C++类对象的隐式类型转换和编译器返回值优化
  • idea左侧项目资源管理器不见了处理
  • Python+深度学习:如何精准评估食品过敏风险?
  • 代码随想录Day20
  • Canal mysql to mysql 增加 online 库同步配置指南
  • MATLAB技巧——命令行输入的绘图,中文是正常的,到了脚本(m文件)里面就变成乱码的解决方法
  • 普通笔记本与军用加固笔记本电脑的区别,探索防水、防爆、防摔的真·移动工作站!