tr1 :: unordered_set union和intersection

时间:2009-05-22 02:31:07

标签: c++ set tr1

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

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

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

3 个答案:

答案 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_setxy,您可以使用以下代码将其交叉点放在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;
    }
}