Scroll to navigation

std::ranges::nth_element(3) C++ Standard Libary std::ranges::nth_element(3)

NAME

std::ranges::nth_element - std::ranges::nth_element

Synopsis


Defined in header <algorithm>
Call signature
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> (1) (since C++20)
constexpr I


nth_element( I first, I nth, S last, Comp comp = {}, Proj proj
= {} );
template< ranges::random_access_range R,


class Comp = ranges::less, class Proj = std::identity >
requires std::sortable<iterator_t<R>, Comp, Proj> (2) (since C++20)
constexpr ranges::borrowed_iterator_t<R>


nth_element( R&& r, iterator_t<R> nth, Comp comp = {}, Proj
proj = {} );


Reorders the elements in [first, last) such that:


* The element pointed at by nth is changed to whatever element would occur in that
position if [first, last) were sorted with respect to comp and proj.
* All of the elements before this new nth element are less than or equal to the
elements after the new nth element. That is, for every iterator i, j in the
ranges [first, nth), [nth, last) respectively, the expression std::invoke(comp,
std::invoke(proj, *j), std::invoke(proj, *i)) evaluates to false.
* If nth == last then the function has no effect.
1) Elements are compared using the given binary comparison function object comp and
projection object proj.
2) Same as (1), but uses r as the range, as if using ranges::begin(r) as first and
ranges::end(r) as last.


The function-like entities described on this page are niebloids, that is:


* Explicit template argument lists cannot be specified when calling any of them.
* None of them are visible to argument-dependent lookup.
* When any of them are found by normal unqualified lookup as the name to the left
of the function-call operator, argument-dependent lookup is inhibited.


In practice, they may be implemented as function objects, or with special compiler
extensions.

Parameters


first, last - the range of elements to reorder
r - the range of elements to reorder
nth - the iterator defining the partition point
comp - comparator used to compare the projected elements
proj - projection to apply to the elements

Return value


1) An iterator equal to last.
2) Same as (1) if r is an lvalue or of a borrowed_range type. Otherwise returns
std::ranges::dangling.

Complexity


Linear in ranges::distance(first, last) on average.

Notes


The algorithm used is typically introselect although other selection algorithms with
suitable average-case complexity are allowed.

Possible implementation


See also the implementation in msvc stl, libstdc++, and libc++: (1) / (2).

Example

// Run this code


#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';
}

Output:


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

See also


ranges::max_element returns the largest element in a range
(C++20) (niebloid)
ranges::min_element returns the smallest element in a range
(C++20) (niebloid)
ranges::partition divides a range of elements into two groups
(C++20) (niebloid)
ranges::partial_sort sorts the first N elements of a range
(C++20) (niebloid)
partially sorts the given range making sure that it is
nth_element partitioned by the given element
(function template)

2024.06.10 http://cppreference.com