冒泡排序在go中能运行但不适用于实际数据,因其时间复杂度为o(n²),10万数据耗时是快排的200倍以上;快排易错在边界和递归终止,且需关注重复值退化与稳定性需求。

冒泡排序在 Go 中能跑通,但别真用它处理实际数据;快速排序写对不难,错在边界条件和递归终止上。
为什么 bubbleSort 的内层循环上限是 n-i-1
每完成一轮外层循环,数组末尾就确定了一个最大值,后续不再参与比较。所以第 i 轮(从 0 开始)时,最后 i+1 个位置已有序,内层只需扫到 n-i-2 索引即可——对应 j 这个条件。
常见错误现象:
- 写成
j :每轮都全量扫描,多做无用比较,性能没优化 - 写成
j :越界访问 <code>arr[j+1],触发 panic: index out of range - 漏掉
-i:完全没体现“冒泡后范围收缩”,退化成固定轮数的暴力交换
quickSort 递归调用时左右子区间怎么切才不漏不重
基准值(pivot)选好后,分区操作必须保证:左半区所有元素 ≤ pivot,右半区所有元素 > pivot,且 pivot 自身最终落位的位置就是分界点。
实操建议:
- 用双指针法分区时,
left从low+1启动,right从high启动,避免把 pivot 自己卷入比较 - 分区结束后,
pivot和right指针位置的值交换,此时right就是 pivot 的最终索引 - 递归调用写成
quickSort(arr, low, right-1)和quickSort(arr, right+1, high),注意是right±1,不是right或right+0 - 终止条件必须是
low >= high,只写low == high会漏掉长度为 2 的子数组
Go 切片传参陷阱:arr 是副本,但底层数组是共享的
Go 函数参数传递是值传递,func bubbleSort(arr []int) 接收的是切片头(包含指针、长度、容量)的副本。这意味着:
- 你能在函数内修改
arr[i],原数组内容会变 —— 因为指针指向同一底层数组 - 但如果你在函数里做了
arr = append(arr, x)或arr = arr[1:],这些操作不影响调用方的原始切片变量 - 所以
bubbleSort不需要返回值,直接改原切片;但如果你希望保持输入不可变,得先copy一份
容易踩的坑:误以为“传切片=传引用”,结果在函数里重切或扩容后,主逻辑还傻等原切片被改 —— 它根本没变。
性能差异不只是理论:10 万整数排序,bubbleSort 耗时通常是 quickSort 的 200 倍以上
这不是夸张。实测中:
-
bubbleSort在随机数据下接近 O(n²),10⁵ 数据量 ≈ 10¹⁰ 次比较+交换,现代 CPU 也要几百毫秒甚至秒级 -
quickSort平均 O(n log n),同量级通常在 5–15ms,快两个数量级 - 更关键的是:冒泡排序的缓存局部性差,每次交换跨度小、内存访问分散;快排分区过程天然有较好空间局部性
- 别依赖 “提前退出” 优化 —— 只有近乎有序数据才生效;真实业务数据几乎不会满足这个前提
真正该关注的,是快速排序在重复值多时的退化问题,以及是否需要稳定排序 —— 这些才是影响你选算法的关键现实约束。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











