白话基数排序
核心原理
按数字从低位到高位(或高位到低位)逐轮分桶排序,逐位规整后整体有序。也就是把数字拆开一位一位看,先排右边个位,再排中间十位,接着排左边百位…… 从右往左一轮轮分桶整理。
通俗步骤
- 确定排序维度(个、十、百、千、万···)和排序顺序(从低到高,从右到左);
- 每一轮,根据当前位数值分配到对应桶,再按桶顺序回填数据;
- 逐位处理完成,数组整体有序。
举例演示 [ 795, 452, 78, 155, 291, 198, 11, 210 ]
确定排序维度和排序顺序
排序维度:个、十、百
排序顺序:个 -> 十 -> 百
第一轮(个位分桶排序)
| 桶(个位) | 桶数据 |
|---|
| 0 | [210] |
| 1 | [291,11] |
| 2 | [452] |
| 5 | [795,155] |
| 8 | [78,198] |
| 回填数据 | [210,291,11,452,795,155,78,198] |
第二轮(十位分桶排序)
| 桶(十位) | 桶数据 |
|---|
| 1 | [210,11] |
| 5 | [452,155] |
| 7 | [78] |
| 9 | [291,795,198] |
| 回填数据 | [210,11,452,155,78,291,795,198] |
第三轮(百位分桶排序)
| 桶区间 | 桶数据 |
|---|
| 0 | [11,78] |
| 1 | [155,198] |
| 2 | [210,291] |
| 4 | [452] |
| 7 | [795] |
| 回填数据 | [210,11,452,155,78,291,795,198] |
代码示例
package main
import "fmt"
func radixSort(arr []int) []int {
if len(arr) == 0 {
return arr
}
maxVal := arr[0]
for _, v := range arr {
if v > maxVal {
maxVal = v
}
}
digit := 1
for maxVal/digit > 0 {
buckets := make([][]int, 10)
for _, num := range arr {
idx := (num / digit) % 10
buckets[idx] = append(buckets[idx], num)
}
arr = arr[:0]
for _, b := range buckets {
arr = append(arr, b...)
}
digit *= 10
}
return arr
}
func main() {
nums := []int{53, 3, 542, 748, 14, 214}
fmt.Println(radixSort(nums))
}
局限性
- 依赖数位,不适合浮点数、无规律长文本;
- 需要额外桶空间;
- 位数越多,轮次越多,性能下降。