找到集合的最快方法

时间:2012-07-06 12:13:47

标签: c++ algorithm stl stl-algorithm

我有成对的int对 set<pair<int,int> > x1, x2, ... xn(n可以在2到20之间)。找到这些集合的最快方法是什么?

抱歉如果我在开始时没有说清楚,我的意思是性能快,内存分配不是问题。

7 个答案:

答案 0 :(得分:10)

假设结果也需要设置,那么您别无选择,只能将每个x_i的每个元素插入到该结果集中。所以明显的实现是:

set<pair<int,int>> x(x1);
x.insert(x2.begin(), x2.end());
// etc

剩下的问题是这是否可以打败速度。

单个元素insert需要position提示,如果正确加速插入。所以可能结果表明这样的事情比x.insert(x2.begin(), x2.end());更快:

auto pos = x.begin()
for (auto it = x2.begin(); it != x2.end(); ++it) {
    pos = x.insert(pos, *it);
}

但这取决于数据:该位置可能准确也可能不准确。您可以在开始之前将所有元素按顺序排列,以确保最佳工具可能是set_union。最好将其命名为merge_and_dedupe_sorted_ranges,因为它的作用与std::set无关。你可以set_union进入中间向量,或者进入这样的集合:

set<pair<int,int>> x;
set_union(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.end());

我对使用set_union的关注是,为了获得以递增顺序将元素添加到集合的好处,每次调用它时都需要创建一个新的空容器(因为如果它不是空的然后添加的元素需要与其中已有的值交错。这些容器的开销可能高于以任意顺序插入集合的开销:您必须对其进行测试。

答案 1 :(得分:6)

不幸的是,我认为你只能使用线性O(N)解决方案,因为所有联合都是两个集合中元素的组合。

template<typename S>
S union_sets(const S& s1, const S& s2)
{
     S result = s1;

     result.insert(s2.cbegin(), s2.cend());

     return result;
}

答案 2 :(得分:5)

首先找到最小集的并集。这是按照设置长度对你的集合进行排序,计算两个最小集合的并集,删除这些集合,根据它的大小将union插入到集合列表中。

如果您测量了两组可能的相似程度,那么您最好首先找到最相似组的联合。这更像是工会操作,可以尽早消除重复。

编辑:对于两组之间的每个联合操作 - 将较小的组合并到较大的组中。

答案 3 :(得分:4)

我假设你的意思是快速实施

然后:std::set_union(*)

两套示例:

#include <set>
#include <algorithm>
#include <iterator>
using namespace std;

int main () {
    set<pair<int,int> > a, b, uni;
    set_union (a.begin(), a.end(),
               b.begin(), b.end(),
               inserter(uni, uni.begin()));

}

对于n组,手写它可能是最易维护的解决方案:

#include <set>
#include <vector>
using namespace std;

int main () {
    vector<set<pair<int,int>>> sets;
    set<pair<int,int>> uni;

    for (const auto &s : sets)
        for (const auto &elem : s)
            uni.insert (elem);
}
但总的来说,人们应该更喜欢标准算法并从质量实施中获益。

如果通过 fast 表示性能,我们无法提供帮助,因为我们没有这些要求。不同的方法可能会针对不同的情况给出不同的结果。


(*)注意:该网站有时因为与标准

不完全准确而感到不满

答案 4 :(得分:3)

在标头算法中尝试set_union。

答案 5 :(得分:2)

您可以使用std::set_union 递归地或简单地将所有集合插入到结果集中(集合消除了重复的项目)。如果项目数量非常小,您可以尝试将其全部插入到矢量中,对其进行排序并在矢量上使用std::unique

答案 6 :(得分:2)

为了节省内存分配并改善位置,最好使用单个vector<T>作为工作内存。

构造一个vector<T>并保留所有s中的元素总数(计算重复数)。然后,从空范围[v.begin(), v.begin())开始,通过附加每个集合的内容,合并和统一来将其扩展为类似集(唯一,已排序)的范围:

vector<T> v;
v.reserve(<total size>);
for (set<T> &s: sets) {
    auto middle = v.insert(v.end(), s.begin(), s.end());
    inplace_merge(v.begin(), middle, v.end());
    v.erase(v.unique(v.begin(), v.end()), v.end());
}