这是我目前在全网找到在golang语言中,最好,思路最清晰的 基数排序实现代码,
基数排序不同于之前所介绍的各类排序,前边介绍到的排序方法或多或少的是通过使用比较和移动记录来实现排序,而基数排序的实现不需要进行对关键字的比较,只需要对关键字进行“分配”与“收集”两种操作即可完成。
例如对无序表{50,123,543,187,49,30,0,2,11,100}
进行基数排序,由于每个关键字都是整数数值,且其中的最大值由个位、十位和百位构成,每个数位上的数字从 0 到 9,首先将各个关键字按照其个位数字的不同进行分配分配表如下所示:
通过按照各关键字的个位数进行分配,按照顺序收集得到的序列变为:{50,30,0,100,11,2,123,543,187,49}
。在该序列表的基础上,再按照各关键字的十位对各关键字进行分配,得到的分配表如下图所示:
由上表顺序收集得到的记录表为:{0、100、2、11、123、30、543、49、50、187}
。在该无序表的基础上,依次将表中的记录按照其关键字的百位进行分配,得到的分配如下图所示:
最终通过三次分配与收集,最终得到的就是一个排好序的有序表:{0、2、11、30、49、50、100、123、187、543}
。
例子中是按照个位-十位-百位的顺序进行基数排序,此种方式是从最低位开始排序,所以被称为最低位优先法(简称“LSD法”)。
害~这么好的代码, 当然我自己写的的啦, 直接上代码:
package sort
import (
"fmt"
"math"
"strconv"
)
/**
基数排序不同于之前所介绍的各类排序,前边介绍到的排序方法或多或少的是通过使用比较和移动记录来实现排序,
而基数排序的实现不需要进行对关键字的比较,只需要对关键字进行“分配”与“收集”两种操作即可完成。
基数排序-LSD
思想:
1. 从所有数据中取出最大值
2. 将所有数据按个个位数到n位数(取决于最大值有),分组,
3. 收集第2步分组之后的数据,可以得到一个新的数据
4.重复2和3,直到分配了最大数的n位数(个位,十位,百位,千位。。。)
*/
// 获取最大数
func getMaxNum(arr []int) int {
if len(arr) == 0 {
panic("空数组")
}
var max = arr[0]
if len(arr) == 1 {
return max
}
for i := 1; i < len(arr); i++ {
if max < arr[i] {
max = arr[i]
}
}
return max
}
/**
int n = 123456;
int unitPlace = n / 1 % 10; 个位
int tenPlace = n / 10 % 10; 十位
int hundredPlace = n / 100 % 10; 百位
int thousandPlace = n / 1000 % 10; 千位
*/
// @params num int 数字
// @params loc int 需要获取从后边开始的第几位
func digit(num int, loc int) int {
return num / int(math.Pow10(loc-1)) % 10
}
// RadixSort 排序
func RadixSort(arr []int) []int {
// 1.获取最大值
maxNum := getMaxNum(arr)
// 进行个位数分配 只用一个桶就可以了
var bucked = map[int][]int{}
// 将元素放进去
maxNumLen := len(strconv.Itoa(maxNum))
startRightLoc := 1
// 最大数有几位,就进行几轮分配
for startRightLoc <= maxNumLen {
for i := 0; i < len(arr); i++ {
// 获取位数
digitLoc := digit(arr[i], startRightLoc)
bucked[digitLoc] = append(bucked[digitLoc], arr[i])
}
// 第几轮结束,依次取数数据
arr = []int{}
for i := 0; i <= 9; i++ {
arr = append(arr, bucked[i]...)
}
bucked = map[int][]int{}
fmt.Printf("第%d轮的数为%v\n", startRightLoc, arr)
startRightLoc++
}
return arr
}