std::ranges::nth_element() 算法
- 自 C++20 起
- 简化
- 详细
// (1)
constexpr I nth_element( I first, I nth, S last, Comp comp = {}, Proj proj = {} );
// (2)
constexpr ranges::borrowed_iterator_t<R>
nth_element( R&& r, iterator_t<R> nth, Comp comp = {}, Proj proj = {} );
参数类型是泛型的,并具有以下约束:
I
-std::random_access_iterator
S
-std::sentinel_for<I>
R
-std::ranges::random_access_range
Comp
- (无)Proj
- (无)
Proj
和 Comp
模板参数对于所有重载都具有以下默认类型:std::identity
、ranges::less
。
此外,每个重载都有以下约束
- (1) -
std::sortable<I, Comp, Proj>
- (2) -
std::sortable<ranges::iterator_t<R>, Comp, Proj>
// (1)
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 = {} );
// (2)
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 = {} );
重新排序 [first
; last
) 中的元素,使得
-
由
nth
指向的元素被更改为如果 [first
;last
) 根据comp
和proj
进行排序时将出现在该位置的任何元素。 -
所有在新
nth
元素之前的元素都小于或等于新nth
元素之后的元素。也就是说,对于范围 [first
;nth
) 和 [nth
;last
) 中的每个迭代器i
和j
,表达式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) 如果
r
是左值或borrowed_range
类型,则与 (1) 相同。否则返回std::ranges::dangling
。
复杂度
平均而言,复杂度为 ranges::distance(first, last)
的线性时间。
异常
(无)
备注
使用的算法通常是 Introselect,尽管也允许使用其他具有合适平均情况复杂度的选择算法。
示例
#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