桶子排序是什么?
桶子排序是一种 把资料分类再逐一排序 的演算法。想像一下你有一堆数字,目标是从小到大排列,但这堆数字范围很大、分布也不均匀。
因此桶子排序的想法就是:
(1) 先根据数字的范围,把它们分进不同的「桶子」里。
(2) 每个桶子里的数字再个别进行排序。
(3) 最后把所有桶子的内容合併在一起,这样数字就排好了!
通常在撰写过程,可注意以下细节
示意图
实作
def bucket_sort(arr, num_buckets=10):
"""
通用桶子排序算法,适用于小数与整数
para:
arr: 输入数字列表
num_buckets: 桶的数量 (预设 10)
return:
排序后的列表
"""
if not arr:
return arr # 空阵列直接回传
# 计算数值范围
min_val, max_val = min(arr), max(arr)
if min_val == max_val:
return arr # 全部数值相同直接回传
# 建立桶阵列
buckets = [[] for _ in range(num_buckets)]
bucket_range = (max_val - min_val) / num_buckets
# 把数字分配到对应的桶
for num in arr:
idx = int((num - min_val) / bucket_range)
idx = min(idx, num_buckets - 1) # 确保最大值进入最后一个桶
buckets[idx].append(num)
# 各桶子排序并合併结果
return [num for bucket in buckets for num in sorted(bucket)]
# 测试五种情境
if __name__ == "__main__":
test_cases = [
[13.5, 0.2, 7.8, 10.1, 1.23, 5.5, 3.14, 8.9], # 小数
[100, 2, 56, 32, 89, 12, 45], # 整数
[0.001, 1000.5, 25.7, 500.2, 0.12, 89.2], # 范围很大
[1, 1, 1, 1, 1], # 相同数值
[5], # 单一值
[] # 空值
]
print("桶子排序测试\\n" + "="*100)
for i, case in enumerate(test_cases, 1):
print(f"测试案例 {i}: \\n原始数组 : {case}")
print(f"排序结果 : {bucket_sort(case)}\\n")
程式码产出如下:
桶子排序测试
====================================================================================================
测试案例 1:
原始数组 : [13.5, 0.2, 7.8, 10.1, 1.23, 5.5, 3.14, 8.9]
排序结果 : [0.2, 1.23, 3.14, 5.5, 7.8, 8.9, 10.1, 13.5]
测试案例 2:
原始数组 : [100, 2, 56, 32, 89, 12, 45]
排序结果 : [2, 12, 32, 45, 56, 89, 100]
测试案例 3:
原始数组 : [0.001, 1000.5, 25.7, 500.2, 0.12, 89.2]
排序结果 : [0.001, 0.12, 25.7, 89.2, 500.2, 1000.5]
测试案例 4:
原始数组 : [1, 1, 1, 1, 1]
排序结果 : [1, 1, 1, 1, 1]
测试案例 5:
原始数组 : [5]
排序结果 : [5]
测试案例 6:
原始数组 : []
排序结果 : []
备注 (for 眼尖的人)
各位应该到这边,应该会有一个疑问,既然我在程式码中就用了 sort 这个指令,为什么我还需要桶子排序? 直接sort一下就行了阿?最大的原因在于,桶子排序先分类再排序,可以减少 sort 的计算时间 (直觉: 给你一堆数值要你去排序,跟帮你分类好再请你排序,谁会比较好排? 显然是后者会更有效率)
因此桶子排序的核心概念是 分类加速,将资料划分为多个小范围(桶),仅对桶内资料排序后合併,完成排序。且其优势在于时间复杂度接近 O(n) (最差就顶多与sort 的 O(n log n) 一样) ,当资料符合以下条件时会感受到极大效率的差异:
(1) 资料分布均匀:均匀分布的资料使每个桶内的资料量接近平均,可大幅减少排序成本,接近线性排序。(2) 资料范围大且分布明确:范围大的资料,若使用桶子排序可以按范围划分,可以缩小排序范围,比直接用 sort() 更高效。
所以,如果资料分布均匀且范围大,桶子排序能够帮助你更好的提高资料处里效率,特别适合巨量资料处理。而对于范围小或随机分布的资料,直接用 sort() 会更简单且快速~