合并多个 STL 容器、删除重复元素的最佳方法?
Posted
技术标签:
【中文标题】合并多个 STL 容器、删除重复元素的最佳方法?【英文标题】:Best way to merge multiple STL containers, removing duplicate elements? 【发布时间】:2008-11-11 15:52:29 【问题描述】:我有两个要合并的 STL 容器,删除任何出现多次的元素。例如:
typedef std::list<int> container;
container c1;
container c2;
c1.push_back(1);
c1.push_back(2);
c1.push_back(3);
c2.push_back(2);
c2.push_back(3);
c2.push_back(4);
container c3 = unique_merge(c1, c2);
// c3 now contains the following 4 elements:
// 1, 2, 3, 4
std::unique 似乎仅适用于相邻元素,在我的情况下,容器可以按任何顺序排列。我猜我可以做一些 std::set 诡计:
container unique_merge(const container& c1, const container& c2)
std::set<container::value_type> s;
BOOST_FOREACH(const container::value_type& val, c1)
s.insert(val);
BOOST_FOREACH(const container::value_type& val, c2)
s.insert(val);
return container(s.begin(), s.end());
有没有更好的方法,还是我错过了明显出血的地方?
【问题讨论】:
如果你要求一些“明显流血”的东西,你的实现对于大多数情况来说已经足够好了。但是确实存在更好的算法,代价是 O(N * log(M)),其中 N 是所有容器中元素的总数,M 是容器的数量。代码不小,以后有时间再写。 @RnMss 真的吗?您可以发布答案吗? ... @user202729 天哪,那是 2014 年... @user202729 现在我不确定了。我认为...,根据我写的内容判断,...也许...当时我认为每个容器都已经排序,但容器的数量可能更大(比如 1000 或更多)。 【参考方案1】:对于无序列表,你的设置技巧可能是最好的之一。每个插入应该是 O(log n),需要 N 个插入,遍历将是 O(n),给你 O(N*log n)。 另一种选择是在每个列表上单独运行 std::sort,然后使用std::set_union 并行遍历它们,这将为您删除重复项。这也将是 O(n*log n),因此如果您担心性能,则必须进行分析。如果不是,请选择对您更有意义的方法。
编辑:
set_union
仅在原始列表中没有重复项时才有效,否则您将不得不使用 sort
、merge
、unique
和 erase
。大 O 性能仍然相同,但对分析有相同的注意事项。
template <typename container>
container unique_merge(container c1, container c2)
std::sort(c1.begin(), c1.end());
std::sort(c2.begin(), c2.end());
container mergeTarget;
std::merge(c1.begin(), c1.end(), c2.begin(), c2.end(),
std::insert_iterator(mergeTarget, mergeTarget.end())
);
std::erase(
std::unique(mergeTarget.begin(), mergeTarget.end()),
mergeTarget.end()
);
return mergeTarget;
【讨论】:
根据std::set_union的规范:如果在R1和R2这两个范围内有重复的元素,说V在R1中出现N次,在R2中出现M次,std的结果: :set_union 将包含 V 的 max(N, M) 个实例。因此,除非 N 这就是我没有测试编译它的结果。【参考方案2】:您将需要排序(显式地,或通过像 set 这样的排序容器隐式地排序)。
有一个常见的习惯用法是使用 std::sort/std::unique/std::erase 来获取容器中的唯一元素。
所以创建一个包含 c1 内容的容器,附加 c2 的内容,然后排序,将唯一元素移到末尾,然后删除它们。像这样的:
container c(c1.begin(), c1.end());
c.insert(c.end(), c2.begin(), c2.end());
c.erase(std::unique(c.begin(), c.end()), c.end());
【讨论】:
【参考方案3】:使用 STL 中的 std::set_union algorithm。不过,您需要先对输入列表进行排序——或者创建输入列表的副本,对其进行排序,然后使用 std::set_union。
【讨论】:
以上是关于合并多个 STL 容器、删除重复元素的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章