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,
RandomIt first, RandomIt nth, RandomIt last );
|
(2) | (C++17 以降) |
template< class RandomIt, class Compare >
void nth_element( RandomIt first, RandomIt nth, RandomIt last,
Compare comp );
|
(3) | (C++20 で constexpr) |
template< class ExecutionPolicy, class RandomIt, class Compare >
void nth_element( ExecutionPolicy&& policy,
RandomIt first, RandomIt nth, RandomIt last,
Compare comp );
|
(4) | (C++17 以降) |
nth_element の要素を再配置し、再配置後に次のようになります:
[first, last)
nthが指す要素は、[first,last)がソートされた場合にその位置に来る要素に変更されます。i内のすべてのイテレータ[first,nth)およびj内のすべてのイテレータ[nth,last)について、次の条件が満たされます:
bool(*j < *i)(C++20 まで)std::less{}(*j, *i)(C++20 以降) は false である。bool(comp(*j, *i)) は false である。
comp に関してソートされる。policy これらのオーバーロードは、以下の式の値が true|
|
(C++20 まで) |
|
|
(C++20 以降) |
次の条件のいずれかが満たされる場合、動作は未定義です:
[first,nth)または[nth,last)が 有効な範囲 ではない。
|
(C++11 まで) |
|
(C++11 以降) |
引数
| first, last | - | 部分ソートする要素の 範囲 を定義するイテレータのペア |
| nth | - | ソートの分割点を定義するランダムアクセスイテレータ |
| policy | - | 使用する 実行ポリシー |
| comp | - | 比較関数オブジェクト(Compare の要件を満たすオブジェクト)。最初の引数が2番目の引数より true小さい(つまり、順序的に 前 である)場合に を返します。 比較関数のシグネチャは以下と同等であるべきです:
シグネチャに |
| 型要件 | ||
-RandomIt は LegacyRandomAccessIterator の要件を満たすこと。
| ||
-Compare は Compare の要件を満たすこと。
| ||
計算量
N を last - first とする:
operator< を使用)(C++20 まで)std::less{}(C++20 以降)、平均。operator< を使用)(C++20 まで)std::less{}(C++20 以降)、および O(N·log(N)) 回のスワップ。comp の適用、平均。comp の適用、および O(N·log(N)) 回のスワップ。例外
テンプレートパラメータ ExecutionPolicy を持つオーバーロードは、以下のようにエラーを報告します:
- アルゴリズムの一部として呼び出された関数が例外を送出し、
ExecutionPolicyが 標準ポリシー のいずれかである場合、std::terminate が呼ばれます。それ以外のExecutionPolicyの場合、動作は実装定義です。 - アルゴリズムがメモリの確保に失敗した場合、std::bad_alloc が送出されます。
実装例
libstdc++、libc++、および MSVC STL の実装も参照してください。
ノート
通常使用されるアルゴリズムは Introselect ですが、適切な平均ケース計算量を持つ他の 選択アルゴリズム も許容されます。
例
#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';
// The consequence of the inequality of elements before/after the Nth one:
assert(std::accumulate(v.begin(), m, 0) < std::accumulate(m, v.end(), 0));
printVec(v);
// Note: comp function changed
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};
The median is 6
v = {3, 2, 3, 4, 5, 6, 10, 7, 9, 6};
The second largest element is 9
The largest element is 10
v = {10, 9, 6, 7, 6, 3, 5, 4, 3, 2};
欠陥報告
以下の動作を変更する欠陥報告は、以前に公開されたC++標準に遡って適用されました。
| DR | 適用先 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 2150 | C++98 | 再配置後、nthの前の1つの要素だけが nth
|
の後の1つの要素より大きくないことが要求されていた要件を修正
要件を修正 |
| LWG 2163 | C++98 | オーバーロード (1) が要素の比較に operator> を使用していた
|
operator<
|
| に変更P0896R4 | C++98 | [first, nth) と [nth, last)が有効な範囲である必要がなかった |
いずれかが無効である場合、動作は未定義 となる |
関連項目
| 範囲内の最大の要素を返す (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
| 範囲内の最小の要素を返す (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
| 範囲の要素をコピーして部分ソートする (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
| 等価な要素間の相対順序を保持しながら範囲の要素をソートする (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
| 範囲の要素をソートする (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
(C++20) |
範囲をソートした場合の N 番目の要素を見つける (アルゴリズム関数オブジェクト) |