tr1 :: unordered_set union和intersection

Ros*_*oss 21 c++ tr1 set

如何在c ++中为tr1 :: unordered_set类型的集合做交集和并集?我找不到太多关于它的参考.

任何参考和代码将受到高度赞赏.非常感谢你.

更新:我只是猜到了tr1 :: unordered_set应该提供交集,联合,差异的函数.因为那是集合的基本操作.当然我可以自己编写一个函数,但我只是想知道是否有来自tr1的内置函数.非常感谢你.

j_r*_*ker 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;
}
Run Code Online (Sandbox Code Playgroud)

假设你有两个unordered_setS,x并且y,你可以把它们的交点在z使用:

unordered_set_intersection(
    x.begin(), x.end(),
    y.begin(), y.end(),
    inserter(z, z.begin())
);
Run Code Online (Sandbox Code Playgroud)

bdonlan的答案不同,这实际上适用于任何键类型,以及容器类型的任何组合(尽管set_intersection()如果源容器被排序,使用当然会更快).

注意:如果存储桶占用率很高,则将每个散列复制到a中可能会更快,在那里vector对它们进行排序set_intersection(),因为在包含n个元素的存储桶中进行搜索是O(n).

  • ...根据你的建议,最好编写一个免费模板函数`intelligently_find <T>()`,它接受对容器的引用(而不是迭代器对),为允许快速查找的容器赋予它重载,然后让它回到`std :: find()`. (5认同)
  • -1回答这个问题:我做了一些实验来确认std :: find是慢的,因此我正在推测@bdonlan的回答.http://ideone.com/Lr64p(谢谢@j_random_hacker) (3认同)
  • 我有点担心.我们确定std :: find与迭代器一起运行到`set`吗?查找不会简单地遍历第二组中的每个元素,而我们希望它使用哈希来循环吗?该函数不应该只是引用set对象然后使用`.count`方法吗? (2认同)
  • 这是unordered_set的set_union:`std :: copy(std :: begin(uset2),std :: end(uset2),std :: inserter(uset1,std :: end(uset1)));` (2认同)

bdo*_*lan 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());
}
Run Code Online (Sandbox Code Playgroud)

  • 您可以通过迭代小集合并测试大集合中的成员资格来加速将大集合与小集合交叉的情况. (8认同)