quickSort不是Go标准库函数,需手动实现;传low和high而非切片副本可避免内存逃逸与GC压力,支持原地排序、精准边界控制及栈安全递归。

quickSort 不是 Go 标准库函数,必须自己实现;直接用 sort.Ints 虽快但不教你怎么思考分治——如果你真想掌握它,得亲手写一个能处理边界、不 panic、且空间可控的版本。
为什么 quickSort 参数要传 low 和 high 而不是切片副本?
传切片副本(如 data[:])看似简洁,但每次递归都分配新底层数组头,造成大量小对象逃逸和 GC 压力。真实工程中更倾向原地排序 + 索引控制:
-
low和high是闭区间下标,避免切片越界 panic(比如data[high+1:]在high == len(data)-1时合法,但data[high+1]会 panic) - 分区函数
partition返回的是基准最终落点的索引,这个值必须和low/high对齐,才能正确切分递归区间 - Go 的切片传递本质是指针 + 长度 + 容量,原地改数据不会影响调用方视图,但能复用同一块内存
partition 里选 arr[high] 当 pivot 时,循环条件为什么是 j ?
因为 arr[high] 已被拎出来当 pivot,它不参与比较,只留作最后“归位”用。若让 j 走到 high,就会拿 pivot 和自己比,导致逻辑错乱或越界读。
- 标准写法中,
for j := low; j ——j只扫[low, high)区间 - 每次
arr[j] 成立时,才把arr[j]换到i+1位置,同时i++;这样结束时i指向最后一个 ≤ pivot 的元素 - 最后 swap
arr[i+1]和arr[high],pivot 就落在了正确位置,左边全 ≤ 它,右边全 > 它
递归调用时 quickSort(arr, low, i) 还是 quickSort(arr, low, i-1)?
取决于 partition 返回值的定义。如果 partition 返回的是 pivot 最终索引 p,那么左右子区间必须是 [low, p-1] 和 [p+1, high] —— 否则 pivot 会被重复排序或漏掉。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 常见错误:写成
quickSort(arr, low, p),结果 pivot 所在位置又被纳入左半区,下次还参与 partition,无限递归或 panic - 另一个坑:递归前没判
low ,空区间(low > high)或单元素(low == high)直接 return,否则栈溢出 - 实测发现,当数组已有序且每次都选末尾为 pivot 时,递归深度达 O(n),Go 默认栈大小可能不够;加个随机 pivot 或切换到
insertionSort处理小数组可缓解
实际项目中要不要手写 quickSort?
绝大多数情况不用。Go 的 sort.Ints 底层就是优化过的混合排序(introsort):小数组用插入排序,中等用快速排序,退化时自动切堆排序,还带 median-of-three 选 pivot。你手写的朴素版,在 10k 元素以上大概率更慢、更占栈、更容易被恶意数据打成 O(n²)。
- 手写唯一合理场景:教学、算法题、或需定制行为(比如按结构体某字段排序 + 稳定性要求 + 自定义相等逻辑)
- 若真要替换标准库,至少得加上 pivot 随机化:
rand.Shuffle先扰动,或pivotIndex := low + rand.Intn(high-low+1)再 swap 到末尾 - 最易被忽略的点:Go 切片的
len和cap在递归中始终不变,但你的逻辑必须只依赖low/high控制范围,否则一不小心就踩到未初始化内存上
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










