跳到主要内容

std::ranges::nth_element() 算法

// (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 - (无)

ProjComp 模板参数对于所有重载都具有以下默认类型:std::identityranges::less

此外,每个重载都有以下约束

  • (1) - std::sortable<I, Comp, Proj>
  • (2) - std::sortable<ranges::iterator_t<R>, Comp, Proj>

重新排序 [first; last) 中的元素,使得

  • nth 指向的元素被更改为如果 [first; last) 根据 compproj 进行排序时将出现在该位置的任何元素。

  • 所有在新 nth 元素之前的元素都小于等于nth 元素之后的元素。也就是说,对于范围 [first; nth) 和 [nth; last) 中的每个迭代器 ij,表达式 std::invoke(comp, std::invoke(proj, *j), std::invoke(proj, *i)) 求值为 false

  • 如果 nth == last,则函数无效。

  • (1) 使用给定的二进制比较函数 comp 和投影 proj 比较元素。

  • (2)(1) 相同,但使用 r 作为源范围,如同使用 ranges::begin(r) 作为 firstranges::end(r) 作为 last

本页描述的函数类实体是niebloids

参数

first
last

要排序的范围。

r

要排序的范围。

nth

定义排序分区点的迭代器。

comp

应用于投影元素的比较对象。

proj

应用于元素的投影。

返回值

复杂度

平均而言,复杂度为 ranges::distance(first, last) 的线性时间。

异常

(无)

备注

使用的算法通常是 Introselect,尽管也允许使用其他具有合适平均情况复杂度的选择算法

示例

Main.cpp
#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
本文源自此 CppReference 页面。它可能为了改进或编辑者的偏好而进行了更改。单击“编辑此页面”查看本文档所做的所有更改。
悬停查看原始许可证。

std::ranges::nth_element() 算法

// (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 - (无)

ProjComp 模板参数对于所有重载都具有以下默认类型:std::identityranges::less

此外,每个重载都有以下约束

  • (1) - std::sortable<I, Comp, Proj>
  • (2) - std::sortable<ranges::iterator_t<R>, Comp, Proj>

重新排序 [first; last) 中的元素,使得

  • nth 指向的元素被更改为如果 [first; last) 根据 compproj 进行排序时将出现在该位置的任何元素。

  • 所有在新 nth 元素之前的元素都小于等于nth 元素之后的元素。也就是说,对于范围 [first; nth) 和 [nth; last) 中的每个迭代器 ij,表达式 std::invoke(comp, std::invoke(proj, *j), std::invoke(proj, *i)) 求值为 false

  • 如果 nth == last,则函数无效。

  • (1) 使用给定的二进制比较函数 comp 和投影 proj 比较元素。

  • (2)(1) 相同,但使用 r 作为源范围,如同使用 ranges::begin(r) 作为 firstranges::end(r) 作为 last

本页描述的函数类实体是niebloids

参数

first
last

要排序的范围。

r

要排序的范围。

nth

定义排序分区点的迭代器。

comp

应用于投影元素的比较对象。

proj

应用于元素的投影。

返回值

复杂度

平均而言,复杂度为 ranges::distance(first, last) 的线性时间。

异常

(无)

备注

使用的算法通常是 Introselect,尽管也允许使用其他具有合适平均情况复杂度的选择算法

示例

Main.cpp
#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
本文源自此 CppReference 页面。它可能为了改进或编辑者的偏好而进行了更改。单击“编辑此页面”查看本文档所做的所有更改。
悬停查看原始许可证。