0

我有一个超边的二维向量以及一个邻接列表。我必须找到hyperEdges[i].size()向量的并集,但我只能找到两个向量的并集。我可以对下面的代码进行哪些改进来做到这一点?我想将联合存储到新声明的二维向量中connectedEdges

void find_union()
{
    connectedEdges.resize(nEdges+1);
    for(int i = 1; i <= nEdges; i++)
    {
        vector<int>::iterator it;
        connectedEdges[i].resize(nEdges+1);

        for(int j = 1; j < hyperEdges[i].size()-1; j++)
        {
            int p = hyperEdges[i][j-1];
            int q= hyperEdges[i][j];
            it = set_union(adjL[p].begin(), adjL[p].end(),adjL[q].begin(),adjL[q].end(), connectedEdges[i].begin());
        connectedEdges[i].resize(it-connectedEdges[i].begin());
        }
    }    
}

例子 : {1,2,4,6,8}

{1,2,3,5,6}

{1,4,7,13,15}

这三组的并集应该是{1,2,3,4,5,6,7,8,13,15} 但是我的程序返回{1,2,3,4,5,6,8}

4

3 回答 3

6

如果您有很多向量,我建议将所有向量的内容插入单个std::set,然后将其转储回std::vector.

像这样的东西:

std::vector<std::vector<int>> src = ...;
std::set<int> all;

for(int i = 0; i < src.size(); i++) {
    all.insert(src[i].begin(), src[i].end());
}

std::vector<int> result(all.begin(), all.end());
于 2015-04-30T13:05:07.957 回答
2

您还可以std::set_union使用所有相邻向量运行(确保它们已排序),逐步构建结果,如下例所示:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

int main()
{
    std::vector<std::vector<int>> v{{1, 1, 2}, {1, 1, 1}, {1, 5, 6, 7}};       
    std::vector<int> result, tmp;
    for(auto&& elem: v)
    {
        std::set_union(elem.begin(), elem.end(), 
                       result.begin(), result.end(),
                       std::back_inserter(tmp));
        result = std::move(tmp); 
        tmp.clear(); // see http://stackoverflow.com/q/9168823/3093378
    }
    // in case you want to remove duplicates
    result.erase(std::unique(result.begin(), result.end()), result.end());
    for(auto&& elem: result)
        std::cout << elem << " "; // 1 2 5 6 7
}
于 2015-04-30T13:28:43.067 回答
1

正如anxieux建议的那样,您可以将它们移入 aset并退出。或者您可以直接手动迭代所有这些:

#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>

std::vector<int> find_union(const std::vector<std::vector<int>>& vecs)
{
    using iter = std::vector<int>::const_iterator;
    using pr = std::pair<iter, iter>;

    // construct pairs of iterators into each vector
    // we will iterate over all of these simultaneously
    std::vector<pr> iter_pairs;
    std::vector<int> results;

    iter_pairs.reserve(vecs.size());
    for (auto& v : vecs) {
        iter_pairs.emplace_back(v.begin(), v.end());
    }   

    while (!iter_pairs.empty()) {
        // pick the next smallest element
        int m = *std::min_element(iter_pairs.begin(), iter_pairs.end(), [](const pr& a, const pr& b){ 
                    return *a.first < *b.first;
                })->first;

        // add it to our results
        results.push_back(m);

        // any vector that contained this element should be advanced
        // if we're done with that vector, remove it
        iter_pairs.erase(
            std::remove_if(iter_pairs.begin(), iter_pairs.end(), [=](pr& p){ 
                if (*p.first == m) {
                    ++p.first;
                    return p.first == p.second;
                }   
                return false;
            }), 
            iter_pairs.end()
            );  
    }   

    return results;
}

int main() {
    for (int i : find_union({{1,2,3}, {1,2,4}, {3,5,42}})) {
        std::cout << i << ' '; // prints 1 2 3 4 5 42
    }   
    std::cout << std::endl;
}
于 2015-04-30T13:25:22.857 回答