std::nth_element
Определён в заголовке <algorithm> | ||
|---|---|---|
template< class RandomIt > void nth_element( RandomIt first, RandomIt nth, RandomIt last ); | (1) | (constexpr начиная с C++20) |
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) | (constexpr начиная с C++20) |
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), который возвращает true, если первый аргумент меньше второго (то есть расположен перед ним). Сигнатура функции сравнения должна быть эквивалентна следующей: boolcmp(constType1&a,constType2&b); Хотя в сигнатуре не обязательно указывать const&, функция не должна изменять переданные ей объекты и должна принимать любые значения типа (возможно, const) |
| Требования к типам | ||
-RandomIt должен удовлетворять требованиям LegacyRandomAccessIterator. |
||
-Compare должен удовлетворять требованиям Compare. |
||
Сложность
Пусть \(\scriptsize N\)N — это last - first:
std::less{}(начиная с C++20).std::less{}(начиная с C++20) и \(\scriptsize O(N \cdot \log(N))\)O(N·log(N)) обменов.comp.comp и \(\scriptsize O(N \cdot \log(N))\)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был не больше одного элемента после nth | требование было исправлено |
| 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-й элемент, который находился бы на этой позиции после сортировки диапазона (объект-функция алгоритма) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/algorithm/nth_element