簡體   English   中英

在C ++中快速建立多個向量的並集

[英]Fast union building of multiple vectors in C++

我正在尋找在C ++中構建多個向量的並集的快速方法。

更具體地說:我有一個向量集合(通常是15-20個vector其中有數千個無符號整數;總是經過排序和唯一,因此它們也可以是std::set )。 對於每個階段,我都選擇其中的一些(通常為5-10個)並建立並集向量。 比我保存聯合向量的長度,然后選擇其他一些向量。 這將完成數千次。 最后,我只對最短聯合向量的長度感興趣。

Small example: 

V1: {0, 4, 19, 40}
V2: {2, 4, 8, 9, 19}
V3: {0, 1, 2, 4, 40}
V4: {9, 10} 

// The Input Vectors V1, V2 … are always sorted and unique (could also be an std::set) 

Choose V1 , V3; 
Union Vector = {0, 1, 2, 4, 19, 40} -> Size = 6; 

Choose V1, V4; 
Union Vector = {0,4, 9, 10, 19 ,40} -> Size = 6; 

… and so on … 

目前,我使用std::set_union但是我敢肯定必須有一個更快的方法。

vector< vector<uint64_t>> collection; 
vector<uint64_t> chosen; 

for(unsigned int i = 0; i<chosen->size(); i++) {
    set_union(collection.at(choosen.at(i)).begin(),
              collection.at(choosen.at(i)).end(),
              unionVector.begin(),
              unionVector.end(),
              back_inserter(unionVectorTmp));
    unionVector.swap(unionVectorTmp);
    unionVectorTmp.clear();
}

感謝您的參考。

編輯27.04.2017一個新的想法:

     unordered_set<unsigned int> unionSet;
     unsigned int counter = 0;

     for(const auto &sel : selection){
        for(const auto &val : sel){
            auto r = unionSet.insert(val);
            if(r.second){
                counter++;
            }
        }
    }

如果對它們進行了排序,則可以在運行時滾動自己的thats O(N + M)。 否則,您可以使用具有類似運行時的哈希表

在C ++ 98中,事實上的方法是set_intersection ,但是對於c ++ 11(或TR1),您可以使用unordered_set ,只要對初始向量進行了排序,您將擁有一個不錯的O(N)算法。

  1. 根據第一個向量構造一個unordered_set
  2. 檢查第二向量的元素是否在集合中

這樣的事情會做:

std::unordered_set<int> us(std::begin(v1), std::end(v1));
auto res = std::count_if(std::begin(v2), std::end(v2), [&](int n) {return us.find(n) != std::end(us);}

無需創建整個聯合矢量。 您可以通過保留迭代器列表並適當地對它們進行比較/遞增來計算所選向量中唯一元素的數量。

這是偽代碼:

int countUnique(const std::vector<std::vector<unsigned int>>& selection)
{
  std::vector<std::vector<unsigned int>::const_iterator> iters;
  for (const auto& sel : selection) {
    iters.push_back(sel.begin());
  }
  auto atEnd = [&]() -> bool {
    // check if all iterators equal end
  };
  int count = 0;
  while (!atEnd()) {
    const int min = 0; // find minimum value among iterators

    for (size_t i = 0; i < iters.size(); ++i) {
      if (iters[i] != selection[i].end() && *iters[i] == min) {
        ++iters[i];
      }
    }

    ++count;
  }
  return count;
}

這利用了您的輸入向量已排序並且僅包含唯一元素的事實。

這個想法是讓迭代器進入每個選定的向量。 這些迭代器中的最小值是聯合向量中的下一個唯一值。 然后,我們遞增所有等於該最小值的迭代器。 我們重復此過程,直到所有迭代器都位於所選向量的末尾。

暫無
暫無

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

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