簡體   English   中英

C ++:2個數組之間的差異

[英]C++: Differences between 2 arrays

我有兩個單個簡單元素類型的未分類隨機訪問數組(int / string / etc,所以有所有比較運算符,可以進行哈希處理等)。 任何一個數組中都不應該有重復的元素。

尋找給出這些數組A和B的一般algorthim會告訴我:

  1. A和B中有哪些元素
  2. A中有哪些元素,但不是B.
  3. B中有哪些元素但不是A.

我想我可以用下面的set運算符來做這個,但是有一個更快的解決方案(例如,不需要我構建兩個有序集合)?

r1 = std::set_intersection(a,b);
r2 = std::set_difference(a,b);
r3 = std::set_difference(b,a);

類似下面的算法會運行O(| A | + | B |)(假設來自unordered_map O(1)行為):

  • 讓list onlyA最初包含所有A,並且只列出onlyBbothAB從空開始。
  • 讓哈希表Amap聯營元素onlyA ,在其相應的迭代onlyA
  • 對於B每個元素b
    • 如果b在Amap中找到相應的迭代器ai
      • b添加到bothAB
      • 使用aionlyA刪除b
    • 否則,將b添加到onlyB

在上面的算法結束時,

  • onlyA包含A中的元素但不包含B中的元素,
  • onlyB包含B中的元素但不包含在A中,
  • 兩個AB都包含A和B中的元素。

以下是上述的實現。 結果以元組< onlyAonlyBbothAB >的形式返回。

template <typename C>
auto venn_ify (const C &A, const C &B) ->
    std::tuple<
        std::list<typename C::value_type>,
        std::list<typename C::value_type>,
        std::list<typename C::value_type>
    >
{
    typedef typename C::value_type T;
    typedef std::list<T> LIST;
    LIST onlyA(A.begin(), A.end()), onlyB, bothAB;
    std::unordered_map<T, typename LIST::iterator> Amap(2*A.size());
    for (auto a = onlyA.begin(); a != onlyA.end(); ++a) Amap[*a] = a;
    for (auto b : B) {
        auto ai = Amap.find(b);
        if (ai == Amap.end()) onlyB.push_back(b);
        else {
            bothAB.push_back(b);
            onlyA.erase(ai->second);
        }
    }
    return std::make_tuple(onlyA, onlyB, bothAB);
}

首先,從你的問題來看,當你談到排序集時,你的意思是std::set是不明確的。 如果是這樣,那么你的第一反應應該是在原始向量上使用std::vector ,如果可以的話。 只需對它們進行排序,然后:

std::vector<T> r1;
std::set_intersection( a.cbegin(), a.cend(), b.cbegin(), b.cend(), std::back_inserter( r1 ) );

對於r2r3

除此之外,我懷疑你能做多少事情。 只需一個循環可以改善一些事情:

std::sort( a.begin(), a.end() );
std::sort( b.begin(), b.end() );
onlyA.reserve( a.size() );
onlyB.reserve( b.size() );
both.reserve( std::min( a.size(), b.size() ) );
auto ita = a.cbegin();
auto enda = a.cend();
auto itb = b.cbegin();
auto endb = b.cend();
while ( ita != enda && itb != endb ) {
    if ( *ita < *itb ) {
        onlyA.push_back( *ita );
        ++ ita;
    } else if ( *itb < *ita ) {
        onlyB.push_back( *itb );
        ++ itb;
    } else {
        both.push_back( *ita );
        ++ ita;
        ++ itb;
    }
}
onlyA.insert( onlyA.end(), ita, enda );
onlyB.insert( onlyB.end(), itb, endb );

reserve可以產生影響,除非大多數元素最終都在同一個向量中,否則可能不會花費太多額外的內存。

您可以通過將A的元素放入unordered_map(其中A中的元素是鍵)來以線性時間執行此操作。 檢查地圖中鍵中B的元素是否存在。

暫無
暫無

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

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