std::ranges::partition_point() 算法
- 自 C++20 起
- 简化
- 详细
// (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>>
- (1) -
Proj
- (无)
对于所有重载,Proj
模板参数的默认类型为 std::identity
。
// (1)
template<
std::forward_iterator I,
std::sentinel_for<I> S,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred
>
constexpr I
partition_point( I first, S last, Pred pred, Proj proj = {} );
// (2)
template<
ranges::forward_range R,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred
>
constexpr ranges::borrowed_iterator_t<R>
partition_point( R&& r, Pred pred, Proj proj = {} );
检查已分区(如同通过ranges::partition
)的范围 [first
; last
) 或 r
,并定位第一个分区的末尾,即不满足 pred
的投影元素,如果所有投影元素都满足 pred
,则为 last
。
本页描述的函数类实体是niebloids。
参数
first last | 要检查的元素范围。 |
r | 要检查的元素范围。 |
pred | 应用于投影元素的谓词。 |
proj | 要应用于元素的投影。 |
返回值
在 [first
; last
) 中第一个分区末尾的迭代器,如果所有投影元素都满足 pred
,则迭代器等于 last
。
复杂度
给定 N
为 ranges::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); });
。
示例
#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