白话桶排序
核心原理
确定数组元素的最大值和最小值,根据元素个数创建同样数量的桶,每个桶代表一个区间,依次把数装入桶,分别对桶内元素单独排序,最后按桶的顺序依次取出所有元素,完成排序。
通俗步骤
- 先创建若干个有序的桶(区间容器);
- 按元素大小,把数据依次放入对应区间桶;
- 每个桶内部单独排序;
- 按桶的顺序依次取出所有元素,整体完成排序。
举例演示 29, 25, 9, 49, 12, 43
确定大小值范围
min:9
max:49
确定区间范围
step = (max - min) / 数组长度 = (49-9) / 6 ≈ 6.67 -> 7
创建区间桶并依次填入数据
| 桶区间 | 桶数据 |
|---|---|
| 3-10 | 9 |
| 11-18 | 12 |
| 19-26 | 25 |
| 27-34 | 29 |
| 35-42 | |
| 43-50 | 49,43 |
桶内单独排序
| 桶区间 | 桶数据 |
|---|---|
| 3-10 | 9 |
| 11-18 | 12 |
| 19-26 | 25 |
| 27-34 | 29 |
| 35-42 | |
| 43-50 | 43,49 |
依次回填数据
9,12,25,29,43,49
代码示例
go
package main
import (
"fmt"
"sort"
)
func bucketSort(arr []int) []int {
if len(arr) == 0 {
return arr
}
// 1. 求最大、最小值
minVal, maxVal := arr[0], arr[0]
for _, v := range arr {
if v < minVal {
minVal = v
}
if v > maxVal {
maxVal = v
}
}
n := len(arr)
bucketNum := n
step := float64(maxVal-minVal) / float64(bucketNum)
// 2. 初始化桶
buckets := make([][]int, bucketNum)
// 3. 元素放入对应桶
for _, num := range arr {
idx := int((float64(num) - float64(minVal)) / step)
// 边界处理:最大值避免下标越界
if idx == bucketNum {
idx--
}
buckets[idx] = append(buckets[idx], num)
}
// 4. 桶内排序 + 拼接结果
var res []int
for _, bucket := range buckets {
sort.Ints(bucket)
res = append(res, bucket...)
}
return res
}
func main() {
nums := []int{29, 25, 9, 49, 12, 43}
sortedNums := bucketSort(nums)
fmt.Println(sortedNums) // [9 12 25 29 43 49]
}
局限性
- 依赖数据分布,分布不均效率暴跌;
- 需要额外空间存放桶;
- 仅适合范围可控的数据。