Golang 计数排序算法
最后修改于 2025 年 3 月 9 日
本教程将介绍 Golang 中的计数排序算法。我们将定义它,展示用于排序数字和文本的示例,并将其与快速排序进行比较。
算法 是解决问题或执行任务的清晰、分步的方法。它是程序处理和管理数据的基础。
排序 将数据按特定顺序排列,例如升序或降序。它在计算中对于组织和检索数据至关重要。
常用排序算法
以下是一些著名的排序算法
- 气泡排序
- 选择排序
- 插入排序
- 归并排序
- 快速排序
- 计数排序
计数排序算法
计数排序是一种非比较排序方法。它计算输入中每个元素出现的次数,然后使用该计数将元素放置在其正确的排序位置。
对于小范围的整数来说它速度很快,但需要额外的内存来存储计数数组。与比较排序不同,它不直接比较元素。
计数排序示例
这是计数排序在 Golang 中对整数的实现。
counting_sort.go
package main import "fmt" func countingSort(arr []int) []int { if len(arr) == 0 { return arr } maxVal := arr[0] for _, num := range arr { if num > maxVal { maxVal = num } } count := make([]int, maxVal+1) for _, num := range arr { count[num]++ } sorted := []int{} for i := 0; i < len(count); i++ { for count[i] > 0 { sorted = append(sorted, i) count[i]-- } } return sorted } func main() { arr := []int{4, 2, 2, 8, 3, 3, 1} sorted := countingSort(arr) fmt.Println("Sorted array:", sorted) }
此代码使用计数排序以升序对整数切片进行排序。
$ go run counting_sort.go Sorted array: [1 2 2 3 3 4 8]
对文本数据进行排序
计数排序也可以对文本进行排序,例如字符串中的字符。这是一个示例
counting_sort_text.go
package main import "fmt" func countingSortText(text string) string { if len(text) == 0 { return text } maxVal := int(rune(text[0])) for _, char := range text { if int(char) > maxVal { maxVal = int(char) } } count := make([]int, maxVal+1) for _, char := range text { count[int(char)]++ } sorted := []rune{} for i := 0; i < len(count); i++ { for count[i] > 0 { sorted = append(sorted, rune(i)) count[i]-- } } return string(sorted) } func main() { text := "counting" sorted := countingSortText(text) fmt.Println("Sorted text:", sorted) }
此代码使用计数排序以升序对字符串中的字符进行排序。
$ go run counting_sort_text.go Sorted text: cginnottu
降序排序
要按降序排序,我们可以在计数排序中反转输出循环。
counting_sort_desc.go
package main import "fmt" func countingSortDesc(arr []int) []int { if len(arr) == 0 { return arr } maxVal := arr[0] for _, num := range arr { if num > maxVal { maxVal = num } } count := make([]int, maxVal+1) for _, num := range arr { count[num]++ } sorted := []int{} for i := len(count) - 1; i >= 0; i-- { for count[i] > 0 { sorted = append(sorted, i) count[i]-- } } return sorted } func main() { arr := []int{4, 2, 2, 8, 3, 3, 1} sorted := countingSortDesc(arr) fmt.Println("Sorted array (descending):", sorted) }
此代码以降序对整数切片进行排序。
$ go run counting_sort_desc.go Sorted array (descending): [8 4 3 3 2 2 1]
与快速排序的比较
计数排序在小整数范围内表现出色,运行时间为 O(n + k),其中 k 是值的范围。快速排序是一种比较排序方法,平均运行时间为 O(n log n),并且能更好地处理更大的数据集。
基准测试示例
此示例比较了计数排序和快速排序的性能。
benchmark.go
package main import ( "fmt" "math/rand" "time" ) func countingSort(arr []int) []int { if len(arr) == 0 { return arr } maxVal := arr[0] for _, num := range arr { if num > maxVal { maxVal = num } } count := make([]int, maxVal+1) for _, num := range arr { count[num]++ } sorted := []int{} for i := 0; i < len(count); i++ { for count[i] > 0 { sorted = append(sorted, i) count[i]-- } } return sorted } func quickSort(arr []int) []int { if len(arr) <= 1 { return arr } pivot := arr[len(arr)/2] left, middle, right := []int{}, []int{}, []int{} for _, x := range arr { if x < pivot { left = append(left, x) } else if x == pivot { middle = append(middle, x) } else { right = append(right, x) } } return append(append(quickSort(left), middle...), quickSort(right)...) } func main() { rand.Seed(time.Now().UnixNano()) data := make([]int, 10000) for i := range data { data[i] = rand.Intn(1000) } start := time.Now() countingSort(append([]int{}, data...)) fmt.Printf("Counting sort time: %.6f seconds\n", time.Since(start).Seconds()) start = time.Now() quickSort(append([]int{}, data...)) fmt.Printf("Quick sort time: %.6f seconds\n", time.Since(start).Seconds()) }
此基准测试在 10,000 个随机整数上测试了这两种算法。计数排序在小范围内可能表现更好,但快速排序的可扩展性更强。
来源
我们已经探讨了 Golang 中的计数排序,并将其与快速排序进行了比较。