std::nth_element
| (1) <algorithm>
|
||
template< class RandomIt >
void nth_element( RandomIt first, RandomIt nth, RandomIt last );
|
(constexpr начиная с C++20) | (2) |
template< class ExecutionPolicy, class RandomIt >
void nth_element( ExecutionPolicy&& policy,
RandomIt first, RandomIt nth, RandomIt last );
|
(начиная с C++17) | (3) |
template< class RandomIt, class Compare >
void nth_element( RandomIt first, RandomIt nth, RandomIt last,
Compare comp );
|
(constexpr начиная с C++20) | (4) |
template< class ExecutionPolicy, class RandomIt, class Compare >
void nth_element( ExecutionPolicy&& policy,
RandomIt first, RandomIt nth, RandomIt last,
Compare comp );
|
(начиная с C++17) | переставляет элементы в |
nth_element таким образом, что после перестановки:
[first, last)Элемент, на который указывает
- заменяется на тот элемент, который оказался бы на этой позиции, если бы
nthбыл отсортирован.[first,last)Для каждого итератора - в
iи каждого итератора[first,nth)вjвыполняется следующее условие:[nth,last)1,2)
bool(*j < *i)(начиная с C++20)std::less{}(*j, *i) является .false3,4)bool(comp(*j, *i)).false1)
comp2,4)policy Эти перегрузки участвуют в разрешении перегрузки только если значение следующего выражения равно true(до C++20)|
|
(начиная с C++20) |
|
|
Если выполняется любое из следующих условий, поведение не определено: |
или
[first,nth)не является[nth,last)допустимым диапазоном.Тип
|
не является |
| Содержание |
first, last
| - | пара итераторов, определяющая | диапазон элементов для частичной сортировки nth |
| - | итератор произвольного доступа, определяющий точку раздела сортировки | policy |
| - | политика выполнения для использования comp | |
| - | функциональный объект сравнения (т.е. объект, удовлетворяющий требованиям | Compare), который возвращает если первый аргумент trueменьше (т.е. упорядочен перед) второго. Сигнатура функции сравнения должна быть эквивалентна следующей:
Хотя сигнатура не обязательно должна содержать
, функция не должна изменять переданные ей объекты и должна иметь возможность принимать все значения типа (возможно const) |
| - | ||
должен соответствовать требованиям RandomItLegacyRandomAccessIterator.
- | ||
должен соответствовать требованиям CompareCompare.
Сложность | ||
Принимая
\( \scriptsize N\) как :
last - first1)
operator<(начиная с C++20)std::less{} в среднем.2)operator<(начиная с C++20)std::less{}, и \( \scriptsize O(N \cdot \log(N))\) обменов.3)comp4)comp\( \scriptsize O(N \cdot \log(N))\) обменов.ИсключенияПерегрузки с параметром шаблона с именем
сообщают об ошибках следующим образом:
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 << "\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исправлено nth
|
требование
LWG 2163 |
| C++98 | перегрузка | (1) использовала для сравнения элементов
operator>изменено на |
P0896R4operator<
|
| C++98 | и | [first, nth) не требовались быть допустимыми диапазонами
[nth, last)поведение не определено |
если любой из них недопустим
См. также |
max_element
| (шаблон функции функциональный объект алгоритма)&ranges::max_element | |
min_element |
|
| (шаблон функции функциональный объект алгоритма)&ranges::min_element | |
partial_sort_copy |
|
| (шаблон функции функциональный объект алгоритма)&ranges::partial_sort_copy | |
stable_sort |
|
| (шаблон функции функциональный объект алгоритма)&ranges::stable_sort | |
sort |
|
| (шаблон функции функциональный объект алгоритма)&ranges::sort | |
ranges::nth_element |
|
находит N-й элемент, если бы диапазон был отсортирован |
(функциональный объект алгоритма) |