如何在C++中应用两个列表之间的交集

How to apply the intersection between two lists in C++?

本文关键字:列表 两个 之间 C++ 应用      更新时间:2023-10-16

我是C++列表的新手。

我有两个列表:list1list2。我需要获取这些列表之间的通用元素。我怎么能拿到这个?

您可以使用:std::set_intersection,前提是您首先对两个列表进行排序:

示例:

#include <algorithm>
#include <iostream>
#include <list>
int main() {
    std::list<int> list1{2, 5, 7, 8, -3, 7};
    std::list<int> list2{9, 1, 6, 3, 5, 2, 11, 0};
    list1.sort();
    list2.sort();
    std::list<int> out;
    std::set_intersection(list1.begin(), list1.end(), list2.begin(), list2.end(),
                          std::back_inserter(out));
     for(auto k : out)
         std::cout << k << ' ';
}

输出:

2 5

编辑:

上面的方法可能不是最优的,主要是因为对std::list进行排序对CPU不好。。。

为了权衡空间,对于较大的数据集,下面的方法肯定会更快,因为我们只对每个列表进行一次迭代,并且每次迭代中完成的所有操作都不会超过O(1)分摊的复杂度

template<typename T>
std::list<T> intersection_of(const std::list<T>& a, const std::list<T>& b){
    std::list<T> rtn;
    std::unordered_multiset<T> st;
    std::for_each(a.begin(), a.end(), [&st](const T& k){ st.insert(k); });
    std::for_each(b.begin(), b.end(),
        [&st, &rtn](const T& k){
            auto iter = st.find(k);
            if(iter != st.end()){
                rtn.push_back(k);
                st.erase(iter);
            }
        }
    );
    return rtn;
}

我使用std::unordered_multiset而不是std::unordered_set,因为它保留了两个列表中常见重复的出现

我在随机生成的9000 int s上为这两种方法运行了一个肮脏的基准测试,结果是(越低越好(:

Average timings for 100 runs:
intersection_of:  8.16 ms
sortAndIntersect: 18.38 ms

使用std::set_intersection方法的分析:

  • 排序大小为N的列表1为:O(Nlog(N))
  • 排序大小为M的列表2为:O(Mlog(M))
  • 寻找交集是:O(M + N)
  • 总计:O( Nlog(N) + Mlog(M) + M + N)。。。(广义为对数(

假设MN相等,我们可以将其推广为:O(Nlog(N))

但如果我们使用我上面发布的intersection_of方法:

  • 遍历大小为N的列表1并添加到集合中为:O(N) + O(1) = O(N)
  • 遍历大小为M列表2,检查多集、添加到out并从中删除:O(M) + O(1) + O(1) + O(1)=O(M)
  • 总计:O(M + N)。。。(广义为线性(

假设MN相等,我们可以将其推广为:O(N)