社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
原理
基数排序的思想其实挺有意思,举个栗子来说,有如下数组:
第一趟:
我们首先对这个数组按照其个位数进行分组,结果如下:
然后将分组后的数据按照索引的大小取出,得到新的数组如下:
第一趟排序后完成的工作为将数组按照个位数由小到大的顺序进行了排序
第二趟:
对第一趟的结果按照十位数进行分组,结果如下:
然后将分组后的数组按照索引的大小分别取出,得到新的数组如下:
第二趟排序后完成的工作是将数组按照十位数由小到大进行了排序,同时由于个位数已经进行了排序,因此将分组后的数组按照索引大小取出时,十位数相同的较小的会排在前面,如31和38,43和49
第三趟:
对第二趟的结果按照百位数进行分组,结果如下:
然后将分组后的数组按照索引的大小分别取出,得到新的数组如下:
第三趟排序后完成的工作是将数组按照百位数由小到大进行了排序,同时由于个位数和十位数都已经进行了排序,所以较小的数会排在前面
这样就完成了整个数组的排序。
由上面的过程可以知道如果最大数有n位,则需要n次(按照索引分组+按照索引大小取出数据)
两个小前提:
1.下面写的算法是对全为正整数的数组进行排序
2.该算法必须要先知道这个数组中最大值得位数,如999是3位
// 基数排序
func BaseSort(data []int) []int {
if len(data) < 2 {
return data
}
max := data[0]
dataLen := len(data)
for i := 1; i < dataLen; i++ {
if data[i] > max {
max = data[i]
}
}
// 计算最大值的位数
maxDigit := 0
for max > 0 {
max = max/10
maxDigit++
}
// 定义每一轮的除数,1,10,100...
divisor := 1;
// 定义了10个桶,为了防止每一位都一样所以将每个桶的长度设为最大,与原数组大小相同
bucket := [10][20]int{{0}}
// 统计每个桶中实际存放的元素个数
count := [10]int{0}
// 获取元素中对应位上的数字,即装入那个桶
var digit int
// 经过maxDigit+1次装通操作,排序完成
for i := 1; i <= maxDigit; i++ {
for j := 0; j < dataLen; j++ {
tmp := data[j]
digit = (tmp / divisor) % 10
bucket[digit][count[digit]] = tmp
count[digit]++
}
// 被排序数组的下标
k := 0
// 从0到9号桶按照顺序取出
for b := 0; b < 10; b++ {
if count[b] == 0 {
continue
}
for c := 0; c < count[b]; c++ {
data[k] = bucket[b][c]
k++
}
count[b] = 0
}
divisor = divisor * 10
}
return data
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!