Spec-Zone.ru › C++

std::nth_element

Defined in header <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) были отсортированы.
  • Все элементы перед этим новым элементом nth меньше или равны элементам после нового элемента nth.

Более формально, nth_element частично сортирует диапазон [first, last) в порядке возрастания таким образом, что для любого i в диапазоне
[first, nth) и для любого j в диапазоне [nth, last) выполняется следующее условие:

1,2) !(*j < *i),
3,4) comp(*j, *i) == false.

Элемент, помещенный в позицию nth, точно соответствует элементу, который бы находился на этом месте, если бы весь диапазон был полностью отсортирован.

nth может быть конечным итератором, в этом случае функция не оказывает никакого влияния.

1) Элементы сравниваются с помощью operator<.
3) Элементы сравниваются с помощью заданной функции сравнения comp.
2,4) То же, что и (1,3), но выполняется в соответствии с policy. Эти перегрузки не участвуют в разрешении перегрузки, если

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, 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 можно было разыменовать и затем неявно преобразовать в оба из них. ​

Требования к типу
-RandomIt должен удовлетворять требованиям ValueSwappable и LegacyRandomAccessIterator.
-Тип разыменованного RandomIt должен удовлетворять требованиям MoveAssignable и MoveConstructible.

Возвращаемое значение

(ничего)

Сложность

1,3) Линейная по std::distance(first, last) в среднем.
2,4) \(\scriptsize O(N)\)O(N) применений предиката и \(\scriptsize O(N \log N)\)O(N \log N) обменов, где N = last - first.

Исключение

Перегрузки с параметром шаблона, имеющим имя ExecutionPolicy сообщают об ошибках следующим образом:

  • Если выполнение функции, вызываемой в рамках алгоритма, вызывает исключение, и ExecutionPolicy является одной из стандартных политик, вызывается std::terminate. Для любой другой ExecutionPolicy, поведение определяется реализацией.
  • Если алгоритм не может выделить память, выбрасывается std::bad_alloc.

Примечания

Используемый алгоритм обычно Introselect, хотя и другие алгоритмы выбора с подходящей сложностью в среднем случае допускаются.

Возможная реализация

См. также реализации в 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};

См. также

max_element
возвращает наибольший элемент в диапазоне
(шаблон функции)
min_element
возвращает наименьший элемент в диапазоне
(шаблон функции)
partial_sort_copy
копирует и частично сортирует диапазон элементов
(шаблон функции)
stable_sort
сортирует диапазон элементов, сохраняя порядок между равными элементами
(шаблон функции)
sort
сортирует диапазон в порядке возрастания
(шаблон функции)
ranges::nth_element
(C++20)
частично сортирует заданный диапазон, гарантируя, что он разбит по заданному элементу
(niebloid)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/nth_element

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API