就像std :: partition根据一元谓词对容器进行分区一样,multi_partition是根据UnaryPredicates ... pred按照UnaryPredicates ...中列出的顺序对容器进行分区,以及顺序中的false元素UnaryPredicates ...以及容器的末尾,并返回所有分区点的列表。但是我没有使用这个辅助函数得到正确的结果:
template <typename ForwardIterator, typename UnaryPredicate, typename... UnaryPredicates>
std::list<ForwardIterator> multi_partition_helper (std::list<ForwardIterator>& partition_points,
ForwardIterator first, ForwardIterator last, UnaryPredicate pred, UnaryPredicates... rest) {
while (true) {
while ((first != last) && pred(*first))
++first;
if (first == last--) break;
while ((first != last) && !pred(*last))
--last;
if (first == last) break;
std::iter_swap (first++, last);
}
partition_points.push_back (first);
multi_partition_helper (partition_points, first, last, rest...);
}
template <typename ForwardIterator, typename UnaryPredicate, typename... UnaryPredicates>
std::list<ForwardIterator> multi_partition_helper (std::list<ForwardIterator>&, ForwardIterator, ForwardIterator) {
// End of recursion.
}
我是否采取了错误的方式?
答案 0 :(得分:4)
一个简单的实现
template <typename BidirIt, typename... Predicates>
void trivial_mul_part( BidirIt first, BidirIt last, Predicates... preds )
{
std::sort( first, last,
[=] (decltype(*first) const& lhs, decltype(*first) const& rhs)
{
return std::make_tuple(preds(lhs)...) > std::make_tuple(preds(rhs)...);
} );
}
可以用作参考算法
真实算法可以用std::partition
本身递归地实现。我的想法是使用n th 谓词调用std::partition
,将迭代器放到n + 1 th 范围的开头,然后使用它进行下一次调用迭代器作为第一个迭代器,n + 1 th 谓词作为谓词。
template <typename BidirIt, typename OutputIterator>
void multi_partition( BidirIt first, BidirIt last, OutputIterator out ) {}
template <typename BidirIt, typename OutputIterator,
typename Pred, typename... Predicates>
void multi_partition( BidirIt first, BidirIt last, OutputIterator out,
Pred pred, Predicates... preds )
{
auto iter = std::partition(first, last, pred);
*out++ = iter;
multi_partition<BidirIt>(iter, last, out, preds...);
}
作为实际算法,可以使用如下:
int arr[] {0, 1, 0, 1, 0, 2, 1, 2, 2};
std::vector<int*> iters;
multi_partition(std::begin(arr), std::end(arr), std::back_inserter(iters),
[] (int i) {return i == 2;},
[] (int i) {return i == 1;});
for (auto i : arr)
std::cout << i << ", ";
std::cout << '\n';
for (auto it : iters)
std::cout << "Split at " << it - arr << '\n';