[英]Does a standard algorithm for sorting and partitioning two ranges in the following way exist?
I wonder whether a standard approach for the following algorithm exists. 我想知道是否存在用于以下算法的标准方法。 I want to sort and partition two ranges
x
and y
. 我想对两个范围
x
和y
进行排序和分区。 Both x
and y
should be partitioned using a binary predicate that takes an element from x
and y
. x
和y
都应使用从x
和y
中获取元素的二进制谓词进行分区。 The signature of the function would be something along the lines of: 该函数的签名应类似于以下内容:
template<typename ForwardIt1, typename ForwardIt2, typename Compare, typename BinaryPredicate>
std::pair<ForwardIt1, ForwardIt2> sort_and_partition(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2, Compare comp, BinaryPredicate p);
Here comp
is forwarded to std::sort
. 在这里
comp
被转发到std::sort
。 The binary predicate p
is used for the partitioning. 二进制谓词
p
用于分区。 Then, for example: 然后,例如:
std::vector<T> x;
std::vector<T> y;
auto [xm, ym] = sort_and_partition(x.begin(), x.end(), y.begin(), y.end(), std::less<T>{}, std::equal_to<T>{});
This would result in four ranges: 这将导致四个范围:
[x.begin(), xm)
[x.begin(), xm)
[xm, x.end())
[xm, x.end())
[y.begin(), ym)
[y.begin(), ym)
[ym, y.end())
[ym, y.end())
Where both x1
and y1
are sorted and contain equivalent elements (according to the binary predicate p
). 其中
x1
和y1
都被排序并包含等效元素(根据二进制谓词p
)。 Effectively x1
and y1
contain the sorted intersection for x
and y
in the example. 有效地
x1
和y1
包含示例中x
和y
的排序交集。 x2
and y2
are sorted as well, and contain all elements unique to x
and y
respectively. x2
和y2
也被排序,并且分别包含x
和y
唯一的所有元素。
Am I missing an obvious approach to implement such an algorithm by combining existing algorithms in the STL? 我是否缺少通过组合STL中的现有算法来实现这种算法的明显方法? I am planning now to write a custom implementation for this but wanted to check here first before starting on the implementation.
我现在打算为此编写一个自定义实现,但是想先在这里进行检查,然后再开始实现。 What would be a good name for this algorithm?
这个算法的好名字是什么?
Update , I've implemented the following algorithm that satisfies my requirements. 更新 ,我实现了满足我的要求的以下算法。 The algorithm requires that the input ranges are sorted.
该算法要求对输入范围进行排序。
/// Takes two sorted input ranges, and partitions both ranges such that all
/// elements that occur in both ranges precede those elements that only occur in
/// one of the two ranges.
template<typename ForwardIt1, typename ForwardIt2, typename Compare>
std::pair<ForwardIt1, ForwardIt2> frc::binary_partition(
ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2, Compare comp)
{
auto equals = [&](const auto& x, const auto& y) { return !comp(x, y) && !comp(y, x); };
// Invariant: first1 and last1 point to the first mismatch.
std::tie(first1, first2) = std::mismatch(first1, last1, first2, last2, equals);
while (first1 != last1 && first2 != last2)
{
// Iterators to the next matching elements.
auto fm1{first1};
auto fm2{first2};
// Find next matching elements in both ranges.
while (comp(*fm1, *fm2) || comp(*fm2, *fm1))
{
if (comp(*fm1, *fm2))
{
++fm1;
}
else
{
++fm2;
}
if (fm1 == last1 || fm2 == last2)
{
return std::pair(first1, first2);
}
}
// Find the end of the matching subsequence.
auto [lm1, lm2] = std::mismatch(fm1 + 1, last1, fm2 + 1, last2, equals);
// In case matching elements are found, move the mismatching subrange behind
// the matching subrange.
first1 = std::rotate(first1, fm1, lm1);
first2 = std::rotate(first2, fm2, lm2);
}
return std::pair(first1, first2);
}
No, and I can think of two reasons: 不,我可以想到两个原因:
You're actually demanding two algorithms: std::sort
and std::stable_partition
(or std::partition
and std::sort
of both partitions of each range). 实际上,您需要两种算法:
std::sort
和std::stable_partition
(或每个范围的两个分区的std::partition
和std::sort
)。 You can compose that yourself. 您可以自己撰写。
Algorithms implement their semantics in terms of iterators - that's where the extra part to make it work with two ranges should be implemented. 算法使用迭代器来实现其语义-在那儿应该实现使它与两个范围一起工作的额外部分。 In other words, if an algorithm's semantics can be defined with one input range, there won't be overloads for multiple ones.
换句话说,如果一种算法的语义可以在一个输入范围内定义,那么多个输入就不会有重载。
You have to use a custom iterator, which will internally manipulate two iterators of distinct ranges (containers). 您必须使用自定义迭代器,该迭代器将在内部操纵两个不同范围的迭代器(容器)。 I think
boost::zip_iterator
is what you're looking for. 我认为
boost::zip_iterator
是您想要的。
There is no such function in STL as far as I know. 据我所知,STL中没有这样的功能。
Maybe what you could do is make use of the following functions provided by STL: 也许您可以做的是利用STL提供的以下功能:
It returns a pair of iterators pointing to the first unmatched element of both sequences. 它返回指向两个序列中第一个不匹配元素的迭代器。
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
pair<InputIterator1, InputIterator2>
mismatch (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, BinaryPredicate pred);
In the case where we can synthesize p
from comp
, this is roughly 在我们可以从
comp
合成p
的情况下,这大概是
template<typename ForwardIt1, typename ForwardIt2, typename Compare>
std::pair<ForwardIt1, ForwardIt2> sort_and_partition(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2, Compare comp)
{
// We don't strictly need copies of the two ranges, but it makes things easier.
// We do want them sorted, using an ordered set here gives that for free
std::multiset<typename std::iterator_traits<ForwardIt1>::value_type, Compare> set1{ first1, last1, comp };
std::multiset<typename std::iterator_traits<ForwardIt2>::value_type, Compare> set2{ first2, last2, comp };
// Copy back into a partitioned [first1, last1)
auto mid1 = std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), first1, comp);
std::set_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), mid1, comp);
// Copy back into a partitioned [first2, last2)
auto mid2 = std::set_intersection(set2.begin(), set2.end(), set1.begin(), set1.end(), first2, comp);
std::set_difference(set2.begin(), set2.end(), set1.begin(), set1.end(), mid2, comp);
// And return our midpoints
return { mid1, mid2 };
}
In the more general case, you will need to decide how many pairs of elements to compare in the partition step, as different choices will lead to different outcomes. 在更一般的情况下,您将需要决定在分区步骤中要比较多少对元素,因为不同的选择将导致不同的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.