c++ - 如何优化 std::set 交集算法 (C++)

标签 c++ optimization

我正在努力完成我的一部分大学作业。我有两个 std::set 容器子集,其中包含指向相当复杂对象的指针,但按不同的标准排序(这就是为什么我不能使用 std::set_intersection())。我需要尽快找到包含在两个子集中的元素。作业有时间/复杂性要求。

我可以在 n*log(m) 时间内完成,其中 n 是第一个子集的大小,m 是大小通过执行以下操作的第二个子集:

for(auto it = subset1.begin(), it != subset1.end(), it++){
    if(find(subset2.begin(), subset2.end(), *it))
        result.insert(*it);
}

这不符合时间要求,即最坏情况是线性的,但平均优于线性。

我找到了以下 question在这里,我发现哈希表方法很有趣。但是,我担心哈希表的创建可能会产生太多开销。集合中包含的类看起来像这样:

class containedInSets {
   //methods
private: 
    vector<string> member1;
    SomeObject member2;
    int member3;
}

我无法控制 SomeObject 类,因此无法为其指定哈希函数。我必须散列指针。此外, vector 可能会增长相当大(在数千个条目中)。

最快的方法是什么?

最佳答案

您的代码不是O(n log(m)),而是O(n * m)

std::find(subset2.begin(), subset2.end(), *it) 是线性的,但是 std::set 有方法 findcountO(log(n)) 中(他们进行二进制搜索)。

所以你可以简单地做:

for (const auto& e : subset1) {
    if (subset2.count(e) != 0) {
        result.insert(e);
    }
}

其复杂度为 n*log(m) 而不是您的 n * m

关于c++ - 如何优化 std::set 交集算法 (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49964288/

相关文章:

c++ - printf/snprintf 格式字符 %N 有什么作用? (不是 %n)

c++ - 套接字接收流在接收到 FIN 数据包时是否关闭?

c++ - 如何在 Windows 上设置 UDP 源地址

python - 交换numpy数组的维度

c# - 如何使我的代码快速

java - 什么更有效率?存储变量引用与不存储变量引用(Android 中的上下文)

c++ - 给定 3 个正整数,找到将它们减少到 0 的最大步数

c++ makefile - 你如何处理混合源文件后缀的规则(例如.cpp和.cxx)

c# - 我在这里重复这个可枚举两次吗?

language-agnostic - 使用 HashMap 将二叉树插入优化为 O(1) 以写入重树