[英]How to apply the intersection between two lists in C++?
我是C ++ 列表的新手。
我有兩個列表: list1
和list2
。 我需要在這些列表之間獲得共同的元素。 我怎么能得到這個?
如果您首先對兩個列表進行排序,則可以使用: 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
上運行了兩個方法的臟基准 ,結果是(越低越好):
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)
...(一般化為對數) 假設M
和N
相等,我們可以將其概括為: O(Nlog(N))
但是如果我們使用上面發布的intersection_of
方法:
N
列表1並添加到集合中: O(N) + O(1) = O(N)
M
列表2進行迭代,檢查多個集合 ,添加到out
,從列表2中刪除: O(M) + O(1) + O(1) + O(1)
= O(M)
O(M + N)
......(廣義為線性) 假設M
和N
相等,我們可以推廣為: O(N)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.