跳到主要内容

std::ranges::partition_point() 算法

// (1)
constexpr I
partition_point( I first, S last, Pred pred, Proj proj = {} );

// (2)
constexpr ranges::borrowed_iterator_t<R>
partition_point( R&& r, Pred pred, Proj proj = {} );

参数类型是泛型的,并具有以下约束

  • I - std::forward_iterator
  • S - std::sentinel_for<I>
  • R - std::ranges::forward_range
  • Pred:
    • (1) - std::indirect_unary_predicate<std::projected<I, Proj>>
    • (2) - std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>>
  • Proj - (无)

对于所有重载,Proj 模板参数的默认类型为 std::identity

检查已分区(如同通过ranges::partition)的范围 [first; last) 或 r,并定位第一个分区的末尾,即不满足 pred 的投影元素,如果所有投影元素都满足 pred,则为 last

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

参数

first
last

要检查的元素范围。

r

要检查的元素范围。

pred

应用于投影元素的谓词。

proj

要应用于元素的投影。

返回值

在 [first; last) 中第一个分区末尾的迭代器,如果所有投影元素都满足 pred,则迭代器等于 last

复杂度

给定 Nranges::distance(first, last)

执行 O(log(N)) 次谓词 pred 和投影 proj 的应用。

然而,如果哨兵不符合std::sized_sentinel_for<I>模型,迭代器增量次数为 O(N)

异常

(无)

可能的实现

partition_point(1) 和 partition_point(2)
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>

auto print_seq = [](auto rem, auto first, auto last)
{
for (std::cout << rem; first != last; std::cout << *first++ << ' ') {}
std::cout << '\n';
};

int main()
{
std::array v {1, 2, 3, 4, 5, 6, 7, 8, 9};

auto is_even = [](int i) { return i % 2 == 0; };

std::ranges::partition(v, is_even);
print_seq("After partitioning, v: ", v.cbegin(), v.cend());

const auto pp = std::ranges::partition_point(v, is_even);
const auto i = std::ranges::distance(v.cbegin(), pp);
std::cout << "Partition point is at " << i << "; v[" << i << "] = " << *pp << '\n';

print_seq("First partition (all even elements): ", v.cbegin(), pp);
print_seq("Second partition (all odd elements): ", pp, v.cend());
}

备注

此算法是ranges::lower_bound的一种更通用形式,后者可以根据ranges::partition_point表示,使用谓词 [&](auto const& e) { return std::invoke(pred, e, value); });

示例

Main.cpp

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>

auto print_seq = [](auto rem, auto first, auto last)
{
for (std::cout << rem; first != last; std::cout << *first++ << ' ') {}
std::cout << '\n';
};

int main()
{
std::array v {1, 2, 3, 4, 5, 6, 7, 8, 9};

auto is_even = [](int i) { return i % 2 == 0; };

std::ranges::partition(v, is_even);
print_seq("After partitioning, v: ", v.cbegin(), v.cend());

const auto pp = std::ranges::partition_point(v, is_even);
const auto i = std::ranges::distance(v.cbegin(), pp);
std::cout << "Partition point is at " << i << "; v[" << i << "] = " << *pp << '\n';

print_seq("First partition (all even elements): ", v.cbegin(), pp);
print_seq("Second partition (all odd elements): ", pp, v.cend());
}
可能的输出
After partitioning, v: 2 4 6 8 5 3 7 1 9
Partition point is at 4; v[4] = 5
First partition (all even elements): 2 4 6 8
Second partition (all odd elements): 5 3 7 1 9
本文档源自此 CppReference 页面。它可能为了改进或编辑者偏好而进行了修改。点击“编辑此页面”查看本文档的所有更改。
悬停查看原始许可证。

std::ranges::partition_point() 算法

// (1)
constexpr I
partition_point( I first, S last, Pred pred, Proj proj = {} );

// (2)
constexpr ranges::borrowed_iterator_t<R>
partition_point( R&& r, Pred pred, Proj proj = {} );

参数类型是泛型的,并具有以下约束

  • I - std::forward_iterator
  • S - std::sentinel_for<I>
  • R - std::ranges::forward_range
  • Pred:
    • (1) - std::indirect_unary_predicate<std::projected<I, Proj>>
    • (2) - std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>>
  • Proj - (无)

对于所有重载,Proj 模板参数的默认类型为 std::identity

检查已分区(如同通过ranges::partition)的范围 [first; last) 或 r,并定位第一个分区的末尾,即不满足 pred 的投影元素,如果所有投影元素都满足 pred,则为 last

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

参数

first
last

要检查的元素范围。

r

要检查的元素范围。

pred

应用于投影元素的谓词。

proj

要应用于元素的投影。

返回值

在 [first; last) 中第一个分区末尾的迭代器,如果所有投影元素都满足 pred,则迭代器等于 last

复杂度

给定 Nranges::distance(first, last)

执行 O(log(N)) 次谓词 pred 和投影 proj 的应用。

然而,如果哨兵不符合std::sized_sentinel_for<I>模型,迭代器增量次数为 O(N)

异常

(无)

可能的实现

partition_point(1) 和 partition_point(2)
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>

auto print_seq = [](auto rem, auto first, auto last)
{
for (std::cout << rem; first != last; std::cout << *first++ << ' ') {}
std::cout << '\n';
};

int main()
{
std::array v {1, 2, 3, 4, 5, 6, 7, 8, 9};

auto is_even = [](int i) { return i % 2 == 0; };

std::ranges::partition(v, is_even);
print_seq("After partitioning, v: ", v.cbegin(), v.cend());

const auto pp = std::ranges::partition_point(v, is_even);
const auto i = std::ranges::distance(v.cbegin(), pp);
std::cout << "Partition point is at " << i << "; v[" << i << "] = " << *pp << '\n';

print_seq("First partition (all even elements): ", v.cbegin(), pp);
print_seq("Second partition (all odd elements): ", pp, v.cend());
}

备注

此算法是ranges::lower_bound的一种更通用形式,后者可以根据ranges::partition_point表示,使用谓词 [&](auto const& e) { return std::invoke(pred, e, value); });

示例

Main.cpp

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>

auto print_seq = [](auto rem, auto first, auto last)
{
for (std::cout << rem; first != last; std::cout << *first++ << ' ') {}
std::cout << '\n';
};

int main()
{
std::array v {1, 2, 3, 4, 5, 6, 7, 8, 9};

auto is_even = [](int i) { return i % 2 == 0; };

std::ranges::partition(v, is_even);
print_seq("After partitioning, v: ", v.cbegin(), v.cend());

const auto pp = std::ranges::partition_point(v, is_even);
const auto i = std::ranges::distance(v.cbegin(), pp);
std::cout << "Partition point is at " << i << "; v[" << i << "] = " << *pp << '\n';

print_seq("First partition (all even elements): ", v.cbegin(), pp);
print_seq("Second partition (all odd elements): ", pp, v.cend());
}
可能的输出
After partitioning, v: 2 4 6 8 5 3 7 1 9
Partition point is at 4; v[4] = 5
First partition (all even elements): 2 4 6 8
Second partition (all odd elements): 5 3 7 1 9
本文档源自此 CppReference 页面。它可能为了改进或编辑者偏好而进行了修改。点击“编辑此页面”查看本文档的所有更改。
悬停查看原始许可证。