跳转至

Bucket sort

拓展到桶排序

如果我们把上述 bucket 中的每个索引想象成一个桶,那么可以将计数排序理解为把 \(n\) 个元素分配到对应的桶中,再根据桶与桶之间天然的有序性来实现排序。

以上解读便是「桶排序 Bucket Sort」的核心思想。具体地,桶排序考虑将 \(n\) 个元素根据大小范围均匀地分配到 \(k\) 个桶中,由于桶之间是有序的,因此仅需在每个桶内部执行排序,最终按照桶之间的大小关系将元素依次排列,即可得到排序结果。

假设使用「快速排序」来排序各个桶内的元素,每个桶内元素数量为 \(\frac{n}{k}\) ,则排序单个桶使用 \(O(\frac{n}{k} \log\frac{n}{k})\) 时间,排序所有桶使用 \(O(n \log\frac{n}{k})\) 时间。当桶数量 \(k\) 接近 \(n\) 时,时间复杂度则趋向于 \(O(n)\)

(图)

理论上桶排序的时间复杂度是 \(O(n)\)但前提是需要将元素均匀分配到各个桶中,而这是不太容易做到的。假设我们要把淘宝中的 \(100\) 万件商品根据价格范围平均分配到 \(100\) 个桶中,由于商品价格不是均匀分布的,比如 \(1\) ~ \(100\) 元的商品非常多、\(1\) 万元以上的商品非常少等,因此难以简单地设定各个桶的价格分界线。解决方案有:

  • 先初步设置一个分界线,将元素分配完后,把元素较多的桶继续划分为多个桶,直至每个桶内元素数量合理为止;该做法一般使用递归实现;
  • 如果我们提前知道商品价格的概率分布,则可以根据已知分布来设置每个桶的价格分界线;值得说明的是,数据分布不一定需要 case-by-case 地统计,有时可以采用一些常见分布来近似,例如自然界的正态分布;

(图)