std::nth_element
| Defined in header <algorithm>
|
||
template< class RandomIt >
void nth_element( RandomIt first, RandomIt nth, RandomIt last );
|
(1) | (constexpr since C++20) |
template< class RandomIt, class Compare >
void nth_element( RandomIt first, RandomIt nth, RandomIt last,
Compare comp );
|
(2) | (constexpr since C++20) |
template< class ExecutionPolicy, class RandomIt >
void nth_element( ExecutionPolicy&& policy,
RandomIt first, RandomIt nth, RandomIt last );
|
(3) | (since C++17) |
template< class ExecutionPolicy, class RandomIt, class Compare >
void nth_element( ExecutionPolicy&& policy,
RandomIt first, RandomIt nth, RandomIt last,
Compare comp );
|
(4) | (since C++17) |
Let [sorted_first, sorted_last) be a sorted hypothetical (random-access) range containing all elements of the target range [first, last). Rearranges elements in the target range such that after the rearrangement:
[first,nth)is a permutation of[sorted_first,sorted_first + (nth - first)).- If
nth == lastisfalse:nthpoints to the element corresponding to the element atsorted_first + (nth - first).[nth + 1,last)is a permutation of[sorted_first + (nth - first) + 1,sorted_last).
[sorted_first, sorted_last) is sorted with respect to operator<(until C++20)std::less{}(since C++20).[sorted_first, sorted_last) is hypothetically sorted with respect to comp.policy.true:
|
|
(until C++20) |
|
|
(since C++20) |
If any of the following conditions is satisfied, the behavior is undefined:
[first,nth)or[nth,last)is not a valid range.
|
(until C++11) |
|
(since C++11) |
Parameters
| first, last | - | the pair of iterators defining the target range |
| nth | - | the iterator indicating the “partition” point |
| comp | - | comparison function object (i.e. an object that satisfies the requirements of Compare) which returns true if the first argument is less than (i.e. is ordered before) the second. The signature of the comparison function should be equivalent to the following:
While the signature does not need to have |
| policy | - | the execution policy to use |
| Type requirements | ||
-RandomIt must meet the requirements of LegacyRandomAccessIterator.
| ||
-Compare must meet the requirements of Compare.
| ||
Complexity
Given N as last - first:
operator<(until C++20)std::less{}(since C++20) on average.comp on average.operator<(until C++20)std::less{}(since C++20), and 𝓞(N·log(N)) swaps.comp, and 𝓞(N·log(N)) swaps.Exceptions
- If the temporary memory resources required for parallelization are not available, std::bad_alloc is thrown.
- If an uncaught exception is thrown while accessing objects via an algorithm argument, the behavior is determined by the execution policy (for standard policies, std::terminate is invoked).
Notes
The algorithm used is typically Introselect although other Selection algorithm with suitable average-case complexity are allowed.
Possible implementation
See also the implementations in libstdc++, libc++, and MSVC STL.
Example
#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <numeric>
#include <vector>
void print_vec(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};
print_vec(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));
print_vec(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';
print_vec(v);
}
Possible output:
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};
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 2150 | C++98 | after the rearrangement, only one element before nthwas required to be not greater than one element after nth
|
corrected the requirement |
| LWG 2163 | C++98 | overload (1) used operator> to compare the elements
|
changed to operator<
|
| P0896R4 | C++98 | [first, nth) and [nth, last)were not required to be valid ranges |
the behavior is undefined if any of them is invalid |
