将多个偏移量的多个元素插入向量中

时间:2019-07-13 12:06:07

标签: c++ c++11 vector c++14

我有一个vector<uint32_t> values和一个vector<std::pair<uint32_t, uint_32_t>> updates,其中包含(大量)累积的向量更新,我想以尽可能便宜的价格制定该向量。

{5, 12}的更新应在12之后插入values[5]不涉及任何其他修改,即values = {10,20,30}和{{ 1}}的结果应为updates = {{0,5}, {1, 6}, {2, 7}}

我想根据values = {10, 5, 20, 6, 30, 7}向量修改向量,如下所示:

updates

如果允许重复的static void update(std::vector<uint32_t>& values, std::vector<std::pair<uint32_t, uint32_t>> updates) { std::sort(updates.begin(), updates.end(), [](std::pair<uint32_t, uint32_t> a, std::pair<uint32_t, uint32_t> b){ return a.first < b.first; }); values.reserve(values.size()+updates.size()); for(uint32_t i = 0; i < updates.size(); ++i){ values.insert(values.begin()+i+updates[i].first, updates[i].second); } } ,则需要使用update[i].first保持相对顺序。

很显然,这段代码相当慢,使用std::stable_sort时间一次将向量的其余部分移回一个。应该有一个更好的解决方案。

关于SO的问题已经非常相似:Insert multiple values into vector。虽然有一个答案可以用来在O(n^2)空间和O(1)时间中更新向量,但是使用c ++ 03时这个问题已经很老了,我想知道是否有一种现代的方法可以做到这一点(甚至,如果我可以避免提前致电O(n))。

1 个答案:

答案 0 :(得分:2)

也许这样的事情应该起作用。由于我们知道所有更新,因此我们知道每个值必须偏移多少才能为新值腾出空间。也就是说,数量恰好等于给定值具有较低索引的更新次数。我们可以从后退,将值移动|updates|位置,插入索引最高的更新,将下一批移动|updates-1|位置,插入第二高的更新...

static void update(std::vector<uint32_t>& values,
    std::vector<std::pair<uint32_t, uint32_t>> updates) {
    std::sort(updates.begin(), updates.end(),[](auto a, auto b){
             return a.first > b.first;//From highest to lowest indices.
        });

    const std::size_t N = values.size();
    std::size_t K = updates.size();
    values.resize(N+K);
    std::size_t end = N;
    for(auto [i,v]:updates){
        //Shift the values in [i+1,end) K positions right
        std::move_backward(values.begin()+i+1,
                           values.begin()+end,
                           values.begin()+end+K);
        //Insert the update
        values[i+K]=v;
        //Preceding values are shifted only by K-1 positions
        --K;
        //Already shifted values
        end=i+1;
    }
}

这需要O(u log u)对更新进行排序,并且需要O(u+n)对旧的更新并添加新的值。仅完成一个resize。请注意,resize对添加的值进行零初始化,此处原始数组的效率会稍高一些。或使用emplace_back做一些索引魔术。