
快速排序(quicksort)是一种高效的、基于比较的排序算法,采用分治(divide and conquer)策略。其基本思想是:
快速排序的平均时间复杂度为O(N log N),但在最坏情况下可能达到O(N^2)。由于其原地(in-place)特性,它在内存使用上非常高效。
在Go语言中,切片([]T)是构建在数组之上的一个抽象,它提供了动态大小和灵活的视图。与固定大小的数组不同,切片可以方便地进行扩展、截取和传递,而底层数据通常保持不变。快速排序通常需要对数据进行原地修改和子数组操作,Go语言的切片非常适合这种场景:
以下是一个使用Go语言切片实现的快速排序函数,它遵循了Lomuto分区方案,并利用了Go语言的一些惯用特性:
package main
import (
"fmt"
"math/rand"
"time"
)
// qsort 对整数切片进行原地快速排序
func qsort(a []int) []int {
// 基线条件:如果切片长度小于2,则无需排序,直接返回
if len(a) < 2 {
return a
}
// 初始化左右指针
left, right := 0, len(a)-1
// 1. 选择枢轴:这里简单地随机选择一个元素作为枢轴
// 注意:更健壮的实现会使用“三数取中”等策略
rand.Seed(time.Now().UnixNano()) // 确保每次运行随机数不同
pivotIndex := rand.Intn(len(a)) // rand.Intn(n) 返回 [0, n) 的随机整数
// 2. 将枢轴移动到最右端,方便后续分区操作
a[pivotIndex], a[right] = a[right], a[pivotIndex]
// 3. 分区操作:将小于枢轴的元素移到左边
// 遍历切片,将小于枢轴的元素与left指针指向的元素交换
for i := range a {
// 枢轴当前在a[right]
if a[i] < a[right] {
a[i], a[left] = a[left], a[i]
left++ // left指针向前移动,指向下一个待交换位置
}
}
// 4. 将枢轴放回其最终位置
// 此时,left指针指向第一个大于或等于枢轴的元素位置
// 将枢轴(原a[right])与a[left]交换
a[left], a[right] = a[right], a[left]
// 5. 递归排序左右子数组
qsort(a[:left]) // 排序左子数组 (不包含枢轴)
qsort(a[left+1:]) // 排序右子数组 (不包含枢轴)
return a
}
func main() {
arr1 := []int{9, 2, 5, 1, 7, 3, 8, 4, 6}
fmt.Printf("Original array: %v\n", arr1)
qsort(arr1)
fmt.Printf("Sorted array: %v\n", arr1) // 输出: Sorted array: [1 2 3 4 5 6 7 8 9]
arr2 := []int{3, 1, 4, 1, 5, 9, 2, 6}
fmt.Printf("Original array: %v\n", arr2)
qsort(arr2)
fmt.Printf("Sorted array: %v\n", arr2) // 输出: Sorted array: [1 1 2 3 4 5 6 9]
arr3 := []int{10}
fmt.Printf("Original array: %v\n", arr3)
qsort(arr3)
fmt.Printf("Sorted array: %v\n", arr3) // 输出: Sorted array: [10]
arr4 := []int{}
fmt.Printf("Original array: %v\n", arr4)
qsort(arr4)
fmt.Printf("Sorted array: %v\n", arr4) // 输出: Sorted array: []
}基线条件 if len(a) < 2 { return a }: 这是递归算法的关键。如果切片的长度小于2(即空切片或只有一个元素的切片),则它已经有序,无需进一步处理,直接返回。
选择枢轴与移动:
立即学习“go语言免费学习笔记(深入)”;
分区操作 for i := range a { ... }:
枢轴归位 a[left], a[right] = a[right], a[left]: 当 for 循环结束后,left 指针指向的位置是第一个大于或等于枢轴的元素,或者所有元素都小于枢轴时的切片末尾。此时,将之前放置在 a[right] 的枢轴元素与 a[left] 处的元素交换,枢轴便回到了它最终的正确位置。此时,left 指针也恰好是枢轴的最终索引。
递归调用 qsort(a[:left]) 和 qsort(a[left+1:]):
通过上述示例,我们展示了如何在Go语言中实现一个地道且高效的原地快速排序算法。这个实现充分利用了Go语言切片引用的特性、简洁的元素交换语法以及递归机制,体现了Go语言在处理数据结构和算法方面的优雅与强大。理解这些Go语言特有的处理方式,对于编写高性能和符合Go语言习惯的代码至关重要。
以上就是使用Go语言切片实现原地快速排序的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号