std::ranges::partition
来自cppreference.com
在标头 <algorithm> 定义 | ||
调用签名 | ||
template<std::permutable I, std::sentinel_for<I> S, class Proj =std::identity, std::indirect_unary_predicate<std::projected<I, Proj>> Pred > | (1) | (C++20 起) |
template<ranges::forward_range R, class Proj =std::identity, std::indirect_unary_predicate< | (2) | (C++20 起) |
1) 重排范围
[
first,
last)
中的元素,使谓词 pred 对 proj 的投影返回 true 的所有元素处于谓词 pred 对 proj 的投影返回 false 的所有元素之前。不保持等价元素的相对顺序。此页面上描述的函数式实体是算法函数对象(非正式地称为 niebloid),即:
目录 |
[编辑]参数
first, last | - | 要重排元素范围的迭代器-哨位对 |
r | - | 要重排的范围 |
pred | - | 应用到投影后元素的谓词 |
proj | - | 应用到谓词的投影 |
[编辑]返回值
始于指向第二组首元素的迭代器,终于等于 last 的迭代器的 subrange
。若 r 是非 borrowed_range
类型的右值则 (2) 返回 std::ranges::dangling。
[编辑]复杂度
给定 N =ranges::distance(first, last),恰好应用 N 次谓词与投影,若 I
实现 ranges::bidirectional_iterator 则至多交换 N/2 次,否则至多交换 N 次。
[编辑]可能的实现
struct partition_fn {template<std::permutable I, std::sentinel_for<I> S, class Proj =std::identity, std::indirect_unary_predicate<std::projected<I, Proj>> Pred>constexprranges::subrange<I> operator()(I first, S last, Pred pred, Proj proj ={})const{ first =ranges::find_if_not(first, last, std::ref(pred), std::ref(proj));if(first == last)return{first, first}; for(auto i =ranges::next(first); i != last;++i){if(std::invoke(pred, std::invoke(proj, *i))){ranges::iter_swap(i, first);++first;}}return{std::move(first), std::move(last)};} template<ranges::forward_range R, class Proj =std::identity, std::indirect_unary_predicate< std::projected<ranges::iterator_t<R>, Proj>> Pred> requires std::permutable<ranges::iterator_t<R>>constexprranges::borrowed_subrange_t<R> operator()(R&& r, Pred pred, Proj proj ={})const{return(*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));}}; inlineconstexpr partition_fn partition; |
[编辑]示例
运行此代码
#include <algorithm>#include <forward_list>#include <functional>#include <iostream>#include <iterator>#include <ranges>#include <vector> namespace ranges = std::ranges; template<class I, std::sentinel_for<I> S, class Cmp =ranges::less> requires std::sortable<I, Cmp>void quicksort(I first, S last, Cmp cmp = Cmp {}){using reference =std::iter_reference_t<I>; if(first == last)return; auto size =ranges::distance(first, last);auto pivot =ranges::next(first, size -1);ranges::iter_swap(pivot, ranges::next(first, size /2)); auto tail = ranges::partition(first, pivot, [=](reference em){returnstd::invoke(cmp, em, *pivot);// em < pivot}); ranges::iter_swap(pivot, tail.begin()); quicksort(first, tail.begin(), std::ref(cmp)); quicksort(ranges::next(tail.begin()), last, std::ref(cmp));} int main(){std::ostream_iterator<int> cout {std::cout, " "}; std::vector<int> v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};std::cout<<"Original vector: \t";ranges::copy(v, cout); auto tail = ranges::partition(v, [](int i){return i %2==0;}); std::cout<<"\nPartitioned vector: \t";ranges::copy(ranges::begin(v), ranges::begin(tail), cout);std::cout<<"│ ";ranges::copy(tail, cout); std::forward_list<int> fl {1, 30, -4, 3, 5, -4, 1, 6, -8, 2, -5, 64, 1, 92};std::cout<<"\nUnsorted list: \t\t";ranges::copy(fl, cout); quicksort(ranges::begin(fl), ranges::end(fl), ranges::greater{});std::cout<<"\nQuick-sorted list: \t";ranges::copy(fl, cout); std::cout<<'\n';}
可能的输出:
Original vector: 0 1 2 3 4 5 6 7 8 9 Partitioned vector: 0 8 2 6 4 │ 5 3 7 1 9 Unsorted list: 1 30 -4 3 5 -4 1 6 -8 2 -5 64 1 92 Quick-sorted list: 92 64 30 6 5 3 2 1 1 1 -4 -4 -5 -8
[编辑]参阅
(C++20) | 复制范围并将元素分为两组 (算法函数对象) |
(C++20) | 判断范围是否已按给定谓词划分 (算法函数对象) |
(C++20) | 将元素分为两组,同时保留其相对顺序 (算法函数对象) |
将范围中元素分为两组 (函数模板) |