在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结构,但是每个向量包含数百万个元素,因此播放的内存总量是几十到几百兆字节
答案 0 :(得分:8)
我至少会尝试:
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
的性质,src
和dst
的大小,以及我们需要优化的原因。
答案 1 :(得分:8)
如果要复制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类型,并且您已经在dst
向量中调整/复制了insert()
溢出保留的可能情况中的所有内容,因此使用{可能更快{1}}转换为新的std::merge()
。这样可以避免初始复制并且具有更好的最坏情况复杂性:
vector
具有O( n )复杂度的最佳情况,但降级为最坏情况O( n log n )取决于您的数据。
inplace_merge()
具有最坏情况的O( n ),因此保证至少同样快,可能更快。它还内置了移动优化。
答案 2 :(得分:0)
如果元素的默认初始化比复制便宜很多,则可以消除insert
调用并调整目标向量的大小。然后实现自己的合并,向后移动 - 将迭代器保留到源的末尾和目标的旧端,然后移动或复制到目标的新端。当你到达源头的开头时,你已经完成了。