C ++中的无序集合交集

时间:2017-12-20 08:02:56

标签: c++ stl unordered-set

这是我的代码,想知道任何让它更快的想法?我的实现是蛮力,对于a中的任何元素,试图找到它是否也在b中,如果是,则放入结果集c。任何更聪明的想法都表示赞赏。

#include <iostream>
#include <unordered_set>

int main() {
    std::unordered_set<int> a = {1,2,3,4,5};
    std::unordered_set<int> b = {3,4,5,6,7};
    std::unordered_set<int> c;
    for (auto i = a.begin(); i != a.end(); i++) {
        if (b.find(*i) != b.end()) c.insert(*i);
    }
    for (int v : c) {
        std::printf("%d \n", v);
    }
}

4 个答案:

答案 0 :(得分:7)

渐近地,你的算法尽可能好。

实际上,我会添加一个检查来循环两个中较小的一组并在较大的一组中进行查找。假设合理均匀分布的哈希值,std::unoredered_set中的查找需要恒定的时间。这样,您将执行更少的此类查找。

答案 1 :(得分:2)

您的算法与无序集合一样好。但是,如果您使用std::set(使用二叉树作为存储)或更好的排序std::vector,您可以做得更好。算法应该是这样的:

  1. 获取a.begin()b.begin()
  2. 的迭代器
  3. 如果迭代器指向相等的元素添加到交集并增加两个迭代器。
  4. 否则递增指向最小值的迭代器
  5. 转到2.
  6. 两者都应该是O(n)时间,但使用普通集应该可以避免计算散列或哈希冲突引起的任何性能下降。

答案 2 :(得分:2)

您可以使用std :: copy_if()

std::copy_if(a.begin(), a.end(), std::inserter(c, c.begin()), [b](const int element){return b.count(element) > 0;} );

答案 3 :(得分:1)

  

谢谢Angew,为什么你的方法更快?你能详细说明一下吗?

好吧,让为您提供一些额外的信息......

应该非常清楚的是,无论您使用哪种数据结构,您都必须迭代其中至少一个中的所有元素,因此您不能比O(n)更好,n是选择迭代的数据结构中的元素数。现在小学是,你可以多快地查找其他结构中的元素 - 使用哈希集,std::unordered_set实际上是O(1) - 这至少是在碰撞次数足够小的情况下( &#34;合理均匀分布的哈希&#34; );退化的情况是所有具有相同密钥的值......

到目前为止,您获得了O(n) * O(1) = O(n)。但您仍然可以选择:O(n)O(m),如果m是另一组中的元素数量。好的,在复杂度计算中,这是相同的,无论如何我们都有一个线性算法,但实际上,如果你选择元素数量较少的集合,你可以省去一些哈希计算和查找......