std::partial_sort 将前N个位置置为最小N个元素(升序),其余位置元素顺序未定义;它重排整个区间,非仅前N位,要求随机访问迭代器,时间复杂度O(N log N)。

std::partial_sort 为什么只排前 N 个,却把整个范围搅乱了?
它不是“取前 N 小再排序”,而是对整个 [first, last) 区间做一次内部重排:前 N 个位置放最小的 N 个元素(升序),其余位置是剩下的元素(顺序未定义,不保证有序也不保证原序)。常见误用是以为它只动前 N 位——实际会读写整个区间。
正确用法必须确保迭代器可随机访问(std::vector、std::array 可以,std::list 不行);否则编译失败。
- 目标是“找最小的 5 个并排好序”?用
std::partial_sort(v.begin(), v.begin() + 5, v.end()) - 想保留原容器后半段顺序?做不到——
std::partial_sort不承诺稳定,也不保留尾部排列 - 只读需求?别用它。它会修改原容器
和 std::nth_element、std::partial_sort_copy 的关键区别在哪?
std::nth_element 只保证第 N 位是“全局第 N 小”,前面无序、后面也无序;std::partial_sort 则让前 N 位升序排列,代价更高(O(N log N) 对比 O(N))。
std::partial_sort_copy 不修改原容器,把结果拷到另一段内存里——适合只读源或目标空间独立的场景。
立即学习“C++免费学习笔记(深入)”;
- 要最小的 10 个且有序 →
std::partial_sort - 只关心中位数或 top-1 是否正确 →
std::nth_element更快 - 原数组不能动,但有足够空间存结果 →
std::partial_sort_copy(src.begin(), src.end(), dst.begin(), dst.begin() + 10)
自定义比较函数传错位置,编译器报什么错?
错误写法:std::partial_sort(v.begin(), v.begin()+3, v.end(), std::greater<int>())</int> —— 看似没问题,但如果 v 是 std::vector<:string></:string>,而你传 std::greater<int>()</int>,就会触发模板推导失败,错误信息通常含 invalid operands to binary expression 或 no match for call。
正确做法:比较函数类型必须能接受迭代器解引用后的类型。字符串按长度排?写 [](const auto& a, const auto& b) { return a.size() 。
- 别依赖 ADL 自动找比较符;显式 lambda 最安全
- 用
std::less/std::greater时,模板参数必须和元素类型一致,比如std::greater<:string>()</:string> - 传函数指针?确保签名是
bool(T, T),不能带额外参数
性能敏感时,partial_sort 的隐藏开销有哪些?
它底层通常用堆(heap-based selection)实现:先建大小为 N 的最大堆(降序取前 N 小),再遍历剩余元素做堆调整。这意味着——
- N 接近 size/2 时,性能急剧退化,接近完整排序;此时直接
std::sort反而更快 - 小 N(比如 N=3)时,常量因子高,可能不如手写三次比较+交换来得快
- 缓存不友好:堆操作跳着访问内存,尤其对大对象(如
std::vector<:array>></:array>)更明显
实测建议:N std::partial_sort 才有明显优势;否则先 profile,别凭直觉选。


















