我有成对的int对
set<pair<int,int> > x1, x2, ... xn
(n可以在2到20之间)。找到这些集合的最快方法是什么?
抱歉如果我在开始时没有说清楚,我的意思是性能快,内存分配不是问题。
答案 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());
}