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 >> 为 true 。 |
(C++20 前) |
|
std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> 为 true 。 |
(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 ) ;
虽然签名不需要包含
const
&
,但函数不得修改传递给它的对象,且必须能够接受所有(可能为const的)
|
| 类型要求 | ||
-
RandomIt
必须满足
LegacyRandomAccessIterator
的要求。
|
||
-
Compare
必须满足
Compare
的要求。
|
||
复杂度
给定 N 为 last - first :
异常
带有名为
ExecutionPolicy
模板参数的重载按以下方式报告错误:
-
如果作为算法一部分调用的函数执行抛出异常,且
ExecutionPolicy是某个 标准策略 ,则调用 std::terminate 。对于其他任何ExecutionPolicy,其行为由实现定义。 - 如果算法无法分配内存,则抛出 std::bad_alloc 。
可能的实现
另请参阅以下实现: libstdc++ 、 libc++ 以及 MSVC STL 。
注释
所采用的算法通常是 Introselect ,但也允许使用其他具有合适平均情况复杂度的 Selection algorithm 。
示例
#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 << "\nThe median is " << 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 << "\nThe second largest element is " << v[1] << '\n'; std::cout << "The largest element is " << 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 后的一个元素 |
修正了
要求条件 |
| LWG 2163 | C++98 | 重载版本 ( 1 ) 使用 operator > 比较元素 | 改为使用 operator < |
| P0896R4 | C++98 |
未要求
[
first
,
nth
)
和
[
nth
,
last
)
是有效范围 |
若任一范围无效
则行为未定义 |
参见
|
返回范围内的最大元素
(函数模板) |
|
|
返回范围内的最小元素
(函数模板) |
|
|
复制并部分排序范围内的元素
(函数模板) |
|
|
排序范围内的元素,同时保持相等元素之间的顺序
(函数模板) |
|
|
将范围按升序排序
(函数模板) |
|
|
(C++20)
|
部分排序给定范围,确保其按给定元素进行划分
(算法函数对象) |