计数排序法
Posted 算法精解
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计数排序法相关的知识,希望对你有一定的参考价值。
简介
计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序)
算法过程
根据待排序集合中最大元素和最小元素的差值范围,申请额外空间;
遍历待排序集合,将每一个元素出现的次数记录到元素值对应的额外空间内;
对额外空间内数据进行计算,得出每一个元素的正确位置;
将待排序集合每一个元素移动到计算得出的正确位置上。
算法实现
计数排序Golang代码如下。
func CountSort(arr []int) []int {
res := make([]int, len(arr))
min, max := arr[0], arr[0]
for _, v:= range arr {
if v > max {
max = v
} else if v < min {
min = v
}
}
// 取排序数组中,元素大小的极值差+1
k := max - min + 1
counts := make([]int, k)
for _, v := range arr {
counts[v - min]++
}
for i := 1; i < len(counts); i++ {
counts[i] += counts[i - 1]
}
for i := len(arr) - 1; i >= 0; i-- {
res[counts[arr[i] - min] - 1] = arr[i]
}
return res
}
func TestCountSort(t *testing.T) {
rand.Seed(time.Now().Unix())
var arr []int
for i := 0; i < 10; i++ {
temp := rand.Intn(1000)
arr = append(arr, temp)
}
originSort := append([]int{}, arr...)
sort.Ints(originSort)
res := countSort.CountSort(arr)
if !reflect.DeepEqual(originSort, res) {
t.Errorf("Got %v for input %v; expected %v", res, arr, originSort)
}
}
测试结果如图1所示。
图1 测试结果
算法分析
以上是关于计数排序法的主要内容,如果未能解决你的问题,请参考以下文章
js冒泡排序法——选择排序(other)——计数排序(桶排序)——快速排序——插入排序-更新