Namespaces
Variants

std::nth_element

От ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Немодифицирующие операции над последовательностями    
Пакетные операции
(C++17)
Операции поиска
Модифицирующие операции над последовательностями
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции генерации
Операции удаления
Операции изменения порядка
(до C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Сортировка и связанные операции
Операции разбиения
(C++11)    

Операции сортировки
Операции бинарного поиска
(на разбитых диапазонах)
Операции над множествами (на отсортированных диапазонах)
Операции слияния (на отсортированных диапазонах)
Операции с кучей
Операции минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановок


Политики выполнения (C++17)
(только для пояснения*)(C++26)execution::sequenced_policy

iota
inner_product
    
accumulate
partial_sum
exclusive_scan    
transform_inclusive_scan
transform_exclusive_scan
Специализированные

алгоритмы<memory>Специализированные

алгоритмы<random>ranges::generate_random
Библиотека C
qsort









 
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)
(до C++20) bool(*j < *i)(начиная с C++20)std::less{}(*j, *i) является .false3,4)
является bool(comp(*j, *i)).false1)


Элементы гипотетически сортируются относительно (до C++20)operator<(начиная с C++20)std::less{}.3)
Элементы гипотетически сортируются относительно .comp2,4)
То же, что и (1,3), но выполняется в соответствии с .policy Эти перегрузки участвуют в разрешении перегрузки только если значение следующего выражения равно
: true(до C++20)

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(начиная с C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

Если выполняется любое из следующих условий, поведение не определено:

или

  • [first, nth) не является [nth, last)допустимым диапазоном.Тип
  • не является *firstSwappable.(до C++11)
не является
  • RandomItValueSwappable.Тип
  • не является *firstMoveConstructible.Тип
  • не является *firstMoveAssignable.(начиная с C++11)
Содержание

first, last

- пара итераторов, определяющая диапазон элементов для частичной сортировки nth
- итератор произвольного доступа, определяющий точку раздела сортировки policy
- политика выполнения для использования comp
- функциональный объект сравнения (т.е. объект, удовлетворяющий требованиям Compare), который возвращает ​ если первый аргумент trueменьше (т.е. упорядочен перед) второго. Сигнатура функции сравнения должна быть эквивалентна следующей:

Хотя сигнатура не обязательно должна содержать

bool cmp(const Type1& a, const Type2& b);

, функция не должна изменять переданные ей объекты и должна иметь возможность принимать все значения типа (возможно const) const& и Type1 независимо от Type2категории значения (таким образом, не допускаетсяType1&, равно как и если только для Type1 перемещение не эквивалентно копированиюType1(начиная с C++11)). Типы
и Type1 должны быть такими, чтобы объект типа Type2 можно было разыменовать, а затем неявно преобразовать к обоим из них. RandomItТребования к типам

-
должен соответствовать требованиям
RandomItLegacyRandomAccessIterator. -
должен соответствовать требованиям
CompareCompare. Сложность

Принимая

\( \scriptsize N\) как : last - first1)

\( \scriptsize O(N)\) сравнений с использованием (до C++20)operator<(начиная с C++20)std::less{} в среднем.2)
\( \scriptsize O(N)\) сравнений с использованием (до C++20)operator<(начиная с C++20)std::less{}, и \( \scriptsize O(N \cdot \log(N))\) обменов.3)
\( \scriptsize O(N)\) применений компаратора в среднем.comp4)
\( \scriptsize O(N)\) применений компаратора , и 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
(шаблон функции
функциональный объект алгоритма)&ranges::sort
ranges::nth_element
находит N-й элемент, если бы диапазон был отсортирован
(функциональный объект алгоритма)