如何在c ++中为tr1 :: unordered_set类型的集合进行交集和并集?我找不到太多关于它的参考。
任何参考和代码都将受到高度赞赏。非常感谢你。
更新:我猜测tr1 :: unordered_set应该提供交集,联合,差异的函数。因为那是集合的基本操作。 当然我可以自己编写一个函数,但我只是想知道是否有来自tr1的内置函数。 非常感谢你。
答案 0 :(得分:17)
我看到set_intersection()
等。来自algorithm
标题将无法正常工作,因为他们明确要求对其输入进行排序 - 猜测您已将其排除在外。
在我看来,迭代哈希A并查找哈希B中的每个元素的“天真”方法实际上应该给你接近最优的性能,因为哈希B中的连续查找将转到相同的哈希桶(假设两个哈希都使用相同的哈希函数)。即使这些存储桶几乎肯定是作为链表实现的,这应该会给你不错的内存位置。
以下是unordered_set_difference()
的一些代码,你可以调整它来制作set union的版本并设置差异:
template <typename InIt1, typename InIt2, typename OutIt>
OutIt unordered_set_intersection(InIt1 b1, InIt1 e1, InIt2 b2, InIt2 e2, OutIt out) {
while (!(b1 == e1)) {
if (!(std::find(b2, e2, *b1) == e2)) {
*out = *b1;
++out;
}
++b1;
}
return out;
}
假设您有两个unordered_set
,x
和y
,您可以使用以下代码将其交叉点放在z
中
unordered_set_intersection(
x.begin(), x.end(),
y.begin(), y.end(),
inserter(z, z.begin())
);
与bdonlan's answer不同,这实际上适用于任何密钥类型,容器类型的任意组合(尽管使用set_intersection()
当然会更快,如果源容器是排序)。
注意:如果存储桶占用率很高,将每个哈希值复制到vector
可能会更快,在那里对它们进行排序和set_intersection()
,因为在包含n个元素的存储桶中进行搜索是O(n)
答案 1 :(得分:14)
没有什么东西 - 为了交叉,只需要通过一个元素的每个元素并确保它在另一个元素中。对于union,添加两个输入集中的所有项目。
例如:
void us_isect(std::tr1::unordered_set<int> &out,
const std::tr1::unordered_set<int> &in1,
const std::tr1::unordered_set<int> &in2)
{
out.clear();
if (in2.size() < in1.size()) {
us_isect(out, in2, in1);
return;
}
for (std::tr1::unordered_set<int>::const_iterator it = in1.begin(); it != in1.end(); it++)
{
if (in2.find(*it) != in2.end())
out.insert(*it);
}
}
void us_union(std::tr1::unordered_set<int> &out,
const std::tr1::unordered_set<int> &in1,
const std::tr1::unordered_set<int> &in2)
{
out.clear();
out.insert(in1.begin(), in1.end());
out.insert(in2.begin(), in2.end());
}
答案 2 :(得分:2)
基于之前的答案:
C ++ 11版本,如果该集支持快速查找功能find()
(返回值有效移动)
/** Intersection and union function for unordered containers which support a fast lookup function find()
* Return values are moved by move-semantics, for c++11/c++14 this is efficient, otherwise it results in a copy
*/
namespace unorderedHelpers {
template<typename UnorderedIn1, typename UnorderedIn2,
typename UnorderedOut = UnorderedIn1>
UnorderedOut makeIntersection(const UnorderedIn1 &in1, const UnorderedIn2 &in2)
{
if (in2.size() < in1.size()) {
return makeIntersection<UnorderedIn2,UnorderedIn1,UnorderedOut>(in2, in1);
}
UnorderedOut out;
auto e = in2.end();
for(auto & v : in1)
{
if (in2.find(v) != e){
out.insert(v);
}
}
return out;
}
template<typename UnorderedIn1, typename UnorderedIn2,
typename UnorderedOut = UnorderedIn1>
UnorderedOut makeUnion(const UnorderedIn1 &in1, const UnorderedIn2 &in2)
{
UnorderedOut out;
out.insert(in1.begin(), in1.end());
out.insert(in2.begin(), in2.end());
return out;
}
}