我正在寻找一种在C ++中构建多个向量联合的快速方法。
更具体地说:我有一组向量(通常是15-20 vector
s,有几千个无符号整数;总是排序且唯一,因此它们也可以是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++;
}
}
}
答案 0 :(得分:2)
如果它们已经排序,你可以在运行时滚动你自己的O(N + M)。否则,您可以使用具有类似运行时的哈希表
答案 1 :(得分:0)
C ++ 98中的事实上的方式是set_intersection,但是对于c ++ 11(或TR1),您可以选择unordered_set,只要初始向量已排序,您将拥有不错的O(N)算法。
这样的事情会发生:
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);}
答案 2 :(得分:0)
无需创建整个联合矢量。您可以通过保留迭代器列表并相应地比较/递增它们来计算所选向量中唯一元素的数量。
这是伪代码:
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;
}
这使用了输入向量已排序且仅包含唯一元素的事实。
这个想法是将迭代器保存到每个选定的向量中。这些迭代器中的最小值是union向量中的下一个唯一值。然后我们递增其值等于该最小值的所有迭代器。我们重复这一步,直到所有迭代器都在所选向量的末尾。