将矢量合并到现有矢量中

时间:2011-07-06 16:47:33

标签: c++ optimization stl

在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结构,但是每个向量包含数百万个元素,因此播放的内存总量是几十到几百兆字节

3 个答案:

答案 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的性质,srcdst的大小,以及我们需要优化的原因。

答案 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调用并调整目标向量的大小。然后实现自己的合并,向后移动 - 将迭代器保留到源的末尾和目标的旧端,然后移动或复制到目标的新端。当你到达源头的开头时,你已经完成了。