将向量合并到现有向量中 在C++中,给出了向量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());

将向量合并到现有向量中 在C++中,给出了向量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());,c++,optimization,stl,C++,Optimization,Stl,??在我关心的情况下,T是一个小的(12-16字节,取决于ABI)POD结构,但每个向量包含数百万个元素,因此可用的内存总量为数十到数百兆字节。我至少会尝试: 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

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

我至少会尝试:

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);
std::vector-tmp;
tmp.reserve(src.size()+dst.size());//评论人士对此可能是正确的
std::merge(src.begin()、src.end()、dst.begin()、dst.end()、std::back_插入器(tmp));
src.swap(tmp);

但是我怀疑这在很大程度上取决于
T
的性质、
src
dst
的大小,以及我们需要优化的原因。

如果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());
\include//for make\u move\u迭代器
size_t n=dst.size();
dst.insert(dst.end(),
std::make_move_迭代器(src.begin()),
std::make_move_迭代器(src.end());
std::in place_merge(dst.begin(),dst.begin()+n,dst.end());
使用
make_move_iterator()
将导致
insert()
src
的内容移动到
dst
中,而不是复制它们

更新:

您正在处理POD类型,并且您已经在调整/复制
dst
向量中的所有内容,可能是
insert()
溢出了保留空间,因此只需将
std::merge()
使用到新的
向量中就可以更快。这将避免初始副本,并具有更好的最坏情况复杂性:

inplace\u merge()
具有O(n)复杂度的最佳情况,但根据您的数据,会退化为最坏情况的O(n log n)


merge()。它还内置了移动优化功能。

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

我认为
inplace\u merge
的最后一个参数应该是
dst.end()
而不是
dst.size()
。马克:您是对的,我的源文件中有它,但在写问题时不知怎么把它弄坏了。现在已修复。@yes123的可能重复:这个问题不是关于合并已排序的向量。为了避免使用
反向插入器增加
tmp
,为什么不将其构造为
std::vector tmp(src.size()+dst.size())
?或者使用
reserve
?@Oli,我宁愿使用
reserve
,以防默认构造很昂贵。这会构造很多元素——为什么不在合并之前只使用
reserve
向量呢?当然,
.reserve()
在这里是个好主意。。。如果
T
是一种讨厌的类型,复制成本很高,那么您可以解包
merge
并将其更改为默认构造,然后从原始结构交换,而不是复制。C++0x有一个
push_back(T&&)
,但是在没有帮助的情况下不能使用,因为被推的东西不一定是一次性的,所以将这个答案与Cory的答案结合起来。最后一行应该是
dst.end()
,您可能会使
n
常量。如果T很难复制,但您的编译器不支持移动语义,您可以调整dst的大小,然后将src的每个元素交换到位。显然,T需要一个优化的交换。我从来没有使用过
inplace\u merge
,但是它看起来好像做了很多赋值和/或复制,这可能会在没有移动的情况下破坏性能。在我关心的情况下,T是一个很小的(12字节,在
向量
中可能填充到16字节)POD结构,所以在我看来,复制和移动都将退化为
memcpy
。是的。在这种情况下,您仍然可以尝试另一个答案中的
合并
建议。他没有说,但是
merge
实际上可以更有效,这取决于您的数据:
inplace\u merge
在最好的情况下是O(n),在最坏的情况下是O(n log n)
merge
始终为O(n)。向量可能有数百万个元素,我认为将所有内容复制到新向量不是一个好主意。