簡體   English   中英

如何在C ++中應用兩個列表之間的交集?

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

我是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上運行了兩個方法的臟基准 ,結果是(越低越好):

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 ,從列表2中刪除: O(M) + O(1) + O(1) + O(1) = O(M)
  • 總計: O(M + N) ......(廣義為線性)

假設MN相等,我們可以推廣為: O(N)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM