Namespaces
Variants

std::ranges::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)

Численные операции
(C++11)
(C++17)
(C++17)    

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

Специализированные <random> алгоритмы
Библиотека C









 
Ограниченные алгоритмы
Все имена в этом меню принадлежат пространству имён std::ranges
Операции последовательности, не изменяющие её
Операции последовательности, изменяющие её
Операции разбиения
Операции сортировки
Операции двоичного поиска (на отсортированных диапазонах)
       
       
Операции над множествами (на отсортированных диапазонах)
Операции с кучей
Операции минимума/максимума
       
       
Операции перестановки
Операции свёртки
Операции над неинициализированной памятью
Типы возврата
 
Определено в заголовке <algorithm>
Сигнатура вызова
template< std::random_access_iterator I, std::sentinel_for<I> S,
          class Comp = ranges::less, class Proj = std::identity >
requires std::sortable<I, Comp, Proj>
constexpr I
    nth_element( I first, I nth, S last, Comp comp = {}, Proj proj = {} );
(1) (начиная с C++20)
template< ranges::random_access_range R,
          class Comp = ranges::less, class Proj = std::identity >
requires std::sortable<iterator_t<R>, Comp, Proj>
constexpr ranges::borrowed_iterator_t<R>
    nth_element( R&& r, iterator_t<R> nth, Comp comp = {}, Proj proj = {} );
(2) (начиная с C++20)

Переупорядочивает элементы в [first, last) таким образом, что:

  • Элемент, на который указывает nth, заменяется на элемент, который оказался бы на этой позиции, если бы [first, last) был отсортирован по отношению к comp и proj.
  • Все элементы перед этим новым nth элементом меньше или равны элементам после нового nth элемента. То есть для каждого итератора i, j в диапазонах [first, nth), [nth, last) соответственно выражение std::invoke(comp, std::invoke(proj, *j), std::invoke(proj, *i)) вычисляется в false.
  • Если nth == last то функция не имеет эффекта.
1) Элементы сравниваются с помощью заданного бинарного объекта функции сравнения comp и объекта проекции proj.
2) То же, что и (1), но использует r в качестве диапазона, как если бы использовал ranges::begin(r) как first и ranges::end(r) как last.

Объекты, подобные функциям, описанные на этой странице, являются объектами алгоритмических функций (неформально известными как niebloids), то есть:

Параметры

first, last - пара итератор-страж, определяющая диапазон элементов для переупорядочивания
r - диапазон элементов для переупорядочивания
nth - итератор, определяющий точку разделения
comp - компаратор, используемый для сравнения проецируемых элементов
proj - проекция, применяемая к элементам

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

1) Итератор, равный last .
2) То же, что и (1) если r является lvalue или имеет тип borrowed_range . В противном случае возвращает std::ranges::dangling .

Сложность

Линейно в среднем по ranges:: distance ( first, last ) в среднем.

Примечания

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

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

Смотрите также реализацию в msvc stl , libstdc++ и libc++: (1) / (2) .

Пример

#include <algorithm>
#include <array>
#include <functional>
#include <iostream>
#include <ranges>
#include <string_view>
void print(std::string_view rem, std::ranges::input_range auto const& a)
{
    for (std::cout << rem; const auto e : a)
        std::cout << e << ' ';
    std::cout << '\n';
}
int main()
{
    std::array v{5, 6, 4, 3, 2, 6, 7, 9, 3};
    print("Before nth_element: ", v);
    std::ranges::nth_element(v, v.begin() + v.size() / 2);
    print("After nth_element:  ", v);
    std::cout << "The median is: " << v[v.size() / 2] << '\n';
    std::ranges::nth_element(v, v.begin() + 1, std::greater<int>());
    print("After nth_element:  ", v);
    std::cout << "The second largest element is: " << v[1] << '\n';
    std::cout << "The largest element is: " << v[0] << "\n\n";
    using namespace std::literals;
    std::array names
    {
        "Diva"sv, "Cornelius"sv, "Munro"sv, "Rhod"sv,
        "Zorg"sv, "Korben"sv, "Bender"sv, "Leeloo"sv,
    };
    print("Before nth_element: ", names);
    auto fifth_element{std::ranges::next(names.begin(), 4)};
    std::ranges::nth_element(names, fifth_element);
    print("After nth_element:  ", names);
    std::cout << "The 5th element is: " << *fifth_element << '\n';
}

Вывод:

Before nth_element: 5 6 4 3 2 6 7 9 3 
After nth_element:  2 3 3 4 5 6 6 7 9 
The median is: 5
After nth_element:  9 7 6 6 5 4 3 3 2 
The second largest element is: 7
The largest element is: 9
Before nth_element: Diva Cornelius Munro Rhod Zorg Korben Bender Leeloo 
After nth_element:  Diva Cornelius Bender Korben Leeloo Rhod Munro Zorg 
The 5th element is: Leeloo

См. также

возвращает наибольший элемент в диапазоне
(объект функции алгоритма)
возвращает наименьший элемент в диапазоне
(объект функции алгоритма)
разделяет диапазон элементов на две группы
(объект функции алгоритма)
сортирует первые N элементов диапазона
(объект функции алгоритма)
находит N-й элемент, если бы диапазон был отсортирован
(шаблон функции)