std::nth_element
在标头 <algorithm> 定义
|
||
template< class RandomIt > void nth_element( RandomIt first, RandomIt nth, RandomIt last ); |
(1) | (C++20 起为 constexpr ) |
template< class ExecutionPolicy, class RandomIt > void nth_element( ExecutionPolicy&& policy, |
(2) | (C++17 起) |
template< class RandomIt, class Compare > void nth_element( RandomIt first, RandomIt nth, RandomIt last, |
(3) | (C++20 起为 constexpr ) |
template< class ExecutionPolicy, class RandomIt, class Compare > void nth_element( ExecutionPolicy&& policy, |
(4) | (C++17 起) |
nth_element
会重排 [
first,
last)
中的元素,使得在重排后:
- nth 指向的元素被更改为假如
[
first,
last)
已排序则该位置会出现的元素。 -
[
first,
nth)
中的每个迭代器 i 和[
nth,
last)
中的每个迭代器 j 满足以下条件:
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> |
(C++20 前) |
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> |
(C++20 起) |
如果满足以下任意条件,那么行为未定义:
-
[
first,
nth)
或[
nth,
last)
不是有效范围。
|
(C++11 前) |
|
(C++11 起) |
参数
first, last | - | 定义待排序范围的随机访问迭代器 |
nth | - | 定义排序划分点的随机访问迭代器 |
policy | - | 所用的执行策略。细节见执行策略。 |
comp | - | 比较函数对象(即满足比较 (Compare) 概念的对象),在第一参数小于(即先 序于)第二参数时返回 true。 比较函数的签名应等价于如下: bool cmp(const Type1 &a, const Type2 &b); 虽然签名不必有 |
类型要求 | ||
-RandomIt 必须满足老式随机访问迭代器 (LegacyRandomAccessIterator) 。
| ||
-Compare 必须满足比较 (Compare) 。
|
复杂度
给定 N 为 last - first:
异常
拥有名为 ExecutionPolicy
的模板形参的重载按下列方式报告错误:
- 如果作为算法一部分调用的函数的执行抛出异常,且
ExecutionPolicy
是标准策略之一,那么调用 std::terminate。对于任何其他ExecutionPolicy
,行为由实现定义。 - 如果算法无法分配内存,那么抛出 std::bad_alloc。
可能的实现
参阅 libstdc++、libc++ 与 msvc stl 中的实现。
注解
典型地使用内省选择算法,但也允许其他拥有适合平均情况复杂度的选择算法。
示例
#include <algorithm> #include <cassert> #include <functional> #include <iostream> #include <numeric> #include <vector> void printVec(const std::vector<int>& vec) { std::cout << "v = {"; for (char sep[]{0, ' ', 0}; const int i : vec) std::cout << sep << i, sep[0] = ','; std::cout << "};\n"; } int main() { std::vector<int> v{5, 10, 6, 4, 3, 2, 6, 7, 9, 3}; printVec(v); auto m = v.begin() + v.size() / 2; std::nth_element(v.begin(), m, v.end()); std::cout << "\n中值为 " << v[v.size() / 2] << '\n'; // 之后导致第 N 个前后的元素互不相等 assert(std::accumulate(v.begin(), m, 0) < std::accumulate(m, v.end(), 0)); printVec(v); // 注意:改变了比较函数 std::nth_element(v.begin(), v.begin() + 1, v.end(), std::greater{}); std::cout << "\n第二大的元素是 " << v[1] << '\n'; std::cout << "最大的元素是 " << v[0] << '\n'; printVec(v); }
可能的输出:
v = {5, 10, 6, 4, 3, 2, 6, 7, 9, 3}; 中值为 6 v = {3, 2, 3, 4, 5, 6, 10, 7, 9, 6}; 第二大的元素是 9 最大的元素是 10 v = {10, 9, 6, 7, 6, 3, 5, 4, 3, 2};
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 2150 | C++98 | 重排后 nth 前只需要有一个元素不大于 nth 后的一个元素 | 改正要求 |
P0896R4 | C++98 | [ first, nth) 和 [ nth, last) 不需要有效
|
其中之一无效时行为未定义 |
参阅
返回范围内的最大元素 (函数模板) | |
返回范围内的最小元素 (函数模板) | |
对范围内的元素进行复制并部分排序 (函数模板) | |
将范围内的元素排序,同时保持相等的元素之间的顺序 (函数模板) | |
将范围按升序排序 (函数模板) | |
(C++20) |
将给定的范围部分排序,确保其按给定元素划分 (niebloid) |