直接用 std::sort 即可,它基于优化的 introsort,比手写指针版快排更稳定高效;仅在底层开发、算法题限制、教学理解分区逻辑等场景才需手写,其核心是双指针扫描与边界检查。

为什么不能直接用 std::sort 就非得手写指针版快排?
除非你在写底层库、做算法题限制 STL 使用,或者教学场景明确要求理解分区逻辑,否则真没必要——std::sort 是优化过的 introsort,比手写快排更稳更快。但如果你正在调试分区边界、搞清楚 partition 里指针怎么挪,那手写指针版确实能暴露所有细节。
partition 函数里指针怎么动才不越界?
核心是双指针扫描:一个从左往右找大于 pivot 的,一个从右往左找小于 pivot 的,交换后继续。容易错在三处:
- 初始
left和right必须落在有效区间内,比如对int* arr排序长度为n,调用时传arr和arr + n - 1,不是arr + n - 移动指针前必须先检查是否越界,比如
while (left ,<code> 要在 <code>++前判断 - 交换后要确保指针继续移动,否则可能卡死在相等元素上;尤其当 pivot 取
*left时,left初始位置的值已参与比较,left++不可省
递归调用时传指针要注意什么?
快排递归分治,每次对子区间排序,传入的必须是真实内存地址,不是偏移量或临时变量地址:
- 左半区:
quicksort(left, pivot_pos - 1)—— 这里pivot_pos是最终 pivot 落点(指针),减 1 后仍是合法地址(只要left ) - 右半区:
quicksort(pivot_pos + 1, right)—— 同理,加 1 后不能超过right,所以递归前要判if (left - 千万别传
&arr[i]这种表达式进递归——如果arr是栈数组,&arr[i]没问题;但如果是new int[n]分配的,就只是普通指针算术,left + 1完全合法
用 int* 实现时性能和稳定性有啥隐患?
裸指针本身不带长度信息,所有边界全靠调用方保证。典型问题:
立即学习“C++免费学习笔记(深入)”;
- 空数组或单元素没提前返回,
left > right时还继续递归,导致访问非法地址 - 重复元素多时,若分区不处理等于 pivot 的情况,可能退化成 O(n²),建议用「三路快排」思想,把等于 pivot 的单独聚在一起
- 没有异常安全机制,万一中间抛异常(比如自定义比较器出错),裸指针不会自动释放资源——这倒不是快排本身的问题,但用指针就要自己担着
实际写的时候,哪怕只是练习,也建议加一句 if (!left || !right || left > right) return; 防住野指针解引用。指针快排的“快”不在代码短,而在你清楚每一处地址算得对不对。


















