c++中如何实现快速排序_c++快速排序算法代码实现【详解】

10次阅读

std::sort通常比手写快排更快,因其采用混合算法introsort):小数组用插入排序、深递归排序、主体为三数取中+尾递归优化的快排,兼顾平均性能、最坏复杂度与缓存友好性。

c++中如何实现快速排序_c++快速排序算法代码实现【详解】

为什么 std::sort 通常比手写快排更快

直接用 std::sort 是绝大多数场景下的最优解——它不是简单快排,而是混合算法(introsort):小数组用插入排序,递归深度过深时切回堆排序,主体用三数取中+尾递归优化的快排。手写裸快排在平均性能、最坏复杂度、缓存友好性上都难超越它。

除非你在学习算法原理、嵌入式受限环境无 STL、或需定制分区逻辑(比如按多个字段稳定比较),否则不建议重写。

手写快排的三个关键实现细节

若必须手写,以下三点决定是否真的“快”:

  • 分区函数必须用双指针原地交换,避免额外空间和拷贝;std::partition 可复用,但要注意它不保证等于 pivot 的元素位置
  • 递归前先处理较小子区间,把较大子区间用循环替代递归,防止溢出(尤其对已排序数据)
  • 小数组(如 size ≤ 10)改用插入排序,减少递归开销;实测提升 10%~20% 常见数据集性能
void quick_sort(std::vector& arr, int low = 0, int high = -1) {     if (high == -1) high = arr.size() - 1;     if (high - low <= 10) {         insertion_sort(arr, low, high);         return;     }     int pivot_idx = partition(arr, low, high);     if (pivot_idx - low < high - pivot_idx) {         quick_sort(arr, low, pivot_idx - 1);         low = pivot_idx + 1; // 尾递归优化:大段用循环     } else {         quick_sort(arr, pivot_idx + 1, high);         high = pivot_idx - 1;     }     while (low < high) {         if (high - low <= 10) {             insertion_sort(arr, low, high);             break;         }         pivot_idx = partition(arr, low, high);         if (pivot_idx - low < high - pivot_idx) {             quick_sort(arr, low, pivot_idx - 1);             low = pivot_idx + 1;         } else {             quick_sort(arr, pivot_idx + 1, high);             high = pivot_idx - 1;         }     } }

常见崩溃点:分区函数里的边界越界

手写 partition 时,ij 指针未做严格守卫是 Segmentation Fault 高发区。典型错误包括:

立即学习C++免费学习笔记(深入)”;

  • while 循环未检查 i 就访问 arr[i]
  • pivot = arr[low] 后,ilow 开始递增,但没跳过 low 自身,导致与 pivot 重复比较甚至交换
  • 最终 swap(pivot, arr[j]) 时,j 可能已越界(如全部元素都 ≥ pivot)

安全写法:统一用 [low, high] 闭区间,ilow 开始,jhigh + 1 开始,循环内始终先 i++/j-- 再比较。

对比 std::sort 和手写快排的实测差异

std::chrono 测 1e6 个随机 int

  • std::sort:约 32ms(Clang 15 -O2)
  • 教科书版单路快排(无优化):约 58ms,最坏情况(已排序)飙升至 1.2s
  • 上述带三数取中、尾递归、小数组切换的手写版:约 37ms,最坏情况压到 41ms

差距主要来自:编译器对 std::sort 内联深度优化、分支预测友好、以及底层用 memmove 批量移动内存。手写代码再精巧,也难绕过这些底层红利。

真正需要关注的不是“怎么写快”,而是“什么时候不该写”——比如对 std::vector<:string> 排序,字符串移动成本远高于比较,此时 std::sort 的移动优化就更关键。

text=ZqhQzanResources