将向量合并到现有向量中

merge vector into existing vector

本文关键字:向量 合并      更新时间:2023-10-16

在c++中,给定vector<T> src, dst,两者都已排序,是否有

更有效的方法将src的内容合并到dst中?
size_t n = dst.size();
dst.insert(dst.end(), src.begin(), src.end());
std::inplace_merge(dst.begin(), dst.begin() + n, dst.end());

?在我所关心的情况下,T是一个小的(12-16字节,取决于ABI) POD结构,但每个向量包含数百万个元素,因此可用的总内存量为数十到数百兆字节。

如果T很难复制,并且编译器支持c++ 0x,则可以更有效地完成。

#include <iterator> // for make_move_iterator
size_t n = dst.size();
dst.insert(dst.end(),
    std::make_move_iterator(src.begin()),
    std::make_move_iterator(src.end()));
std::inplace_merge(dst.begin(), dst.begin() + n, dst.end());

使用make_move_iterator()将导致insert()src的内容移动到dst中,而不是复制它们。

更新:

您正在处理POD类型,并且您已经在insert()溢出储备的可能情况下调整/复制dst向量中的所有内容,因此将std::merge()使用到新的vector中可能会更快。这将避免初始复制并具有更好的最坏情况复杂度:

inplace_merge()具有O(n)复杂度的最佳情况,但根据您的数据退化为最坏情况O(n log n)。

merge()有一个最坏情况O(n),所以它保证至少是一样快的,可能更快。它还内置移动优化

我至少会试试:

std::vector<T> tmp;
tmp.reserve(src.size() + dst.size()); // commenters are probably right about this
std::merge(src.begin(), src.end(), dst.begin(), dst.end(), std::back_inserter(tmp));
src.swap(tmp);

但我怀疑这在很大程度上取决于T的性质,srcdst的大小,以及我们为什么需要优化。

如果元素的默认初始化比复制便宜得多,则可以消除insert调用并调整目标向量的大小。然后实现您自己的合并,倒着——将迭代器保持在源端和目标端的旧端,并将其移动或复制到目标端的新端。当您到达源的开头时,您就完成了。