std::partial_sort将最小(或最大)的n个元素放到开头并有序排列,需传入first、middle、last三个迭代器,且必须满足distance(first, last) >= distance(first, middle)。

std::partial_sort 的正确调用方式
它不是“只排前 N 个”,而是“把最小(或最大)的 N 个元素放到开头,并保证它们有序”。关键在于传入三个迭代器:first、middle、last,其中 [first, middle) 是你要得到的已排序的前 N 个位置,[middle, last) 是剩余未排序部分。
常见错误是误以为传入 N 就能自动截断——它根本不接受整数 N,只认迭代器范围。
- 要取前 5 个最小元素并升序排列?写
std::partial_sort(v.begin(), v.begin() + 5, v.end()) - 容器长度小于 N?运行时行为未定义——必须确保
distance(first, last) >= distance(first, middle) - 如果只想取最小值但不关心顺序?用
std::nth_element更快;如果还要前 N 个有序,partial_sort才合适
为什么不能直接用 std::sort(v.begin(), v.begin() + N)
std::sort(v.begin(), v.begin() + N) 只对前 N 个位置排序,但不保证它们是整个容器里最小的 N 个——它只是局部排序。结果可能包含很大值,而真正的最小值却被留在后面。
比如 v = {9, 8, 7, 6, 5, 4, 3, 2, 1},执行 sort(begin, begin+3) 后前三个仍是 {9,8,7}(已排成 {7,8,9}),但全局最小的三个其实是 {1,2,3}。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
partial_sort会重排整个范围,把最小的 N 个“拉”到前面并排序 - 时间复杂度是
O(N log N + (last-first) log N),比全排序O(n log n)更优,尤其当 N - 如果 N 接近 n,不如直接用
std::sort——常数开销反而更大
自定义比较函数与降序取最大 N 个
默认按升序找最小 N 个。要取最大的 N 个并降序排列(即前 N 个是最大、次大……),需传入 std::greater:
std::partial_sort(v.begin(), v.begin() + 3, v.end(), std::greater{});
注意:这会让前 3 个是最大、第二大、第三大,且从大到小排列(即 [max, second_max, third_max])。如果只要最大 N 个、不要求顺序,还是优先考虑 nth_element。
- 比较函数必须满足严格弱序;用
lambda时捕获要谨慎,避免悬垂引用 - 对
vector<string></string>按长度排序?写[](const auto& a, const auto& b) { return a.size() - 如果容器是
const或只读视图,得先拷贝一份——partial_sort必须可写
容易被忽略的边界和性能陷阱
最常踩的坑是没检查 middle 是否合法。例如对空容器或 size v.begin() + N,直接触发未定义行为(多半 crash)。
- 安全写法:先判断
if (v.size() ,再调用 <code>partial_sort(v.begin(), v.begin() + N, v.end()) - 对
std::list不能用partial_sort——它要求随机访问迭代器;改用list.sort()+ 截断,或转存到vector - 多线程环境下,别在另一个线程正修改同一容器时调用它——没有内部同步
真正要注意的从来不是语法怎么写,而是你是否清楚自己要的是“全局最小的 N 个有序”,而不是“前 N 个局部有序”。漏掉这个前提,函数再对也没用。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










