假设我有一个名为std::vector<int>
的已排序v
。我增加了v[i]
的值,并且想对向量进行重新排序。假设我希望仅将v[i]
增加一点。以下肯定是错误的。
// (WRONG)
int x = v[i]; // the new v[i], that is
v.erase(v.begin() + i);
v.insert(
std::upper_bound(v.begin() + i, v.end(), x),
x
);
这是错误的,因为删除时我几乎将整个数组移回,插入时又将其向前移动,而我可能只需要稍微增加v[i]
,这只需要移动几个条目即可。另一个想法可能是:
int x = v[i]; // the new v[i], that is
if (/* new v[i] is > old v[i] */) {
size_t j = i + 1;
while (v[j] < x && j < v.size()) {
std::swap(v[j-1], v[j])
j++;
}
}
,如果我减少v[i]
而不是增加它,则类似。这是最好的吗?
假设我无权访问boost::flat_set
。 (不确定是否可以轻松地做到这一点。)如果已回答,则表示歉意。搜索没有找到答案。
答案 0 :(得分:3)
使用std::rotate
将元素移动到新位置。如果您确实认为它不会走太远,则线性搜索新位置可能会更快(或通过检查距旧位置两倍的距离以找到upper_bound
的边界来应用混合方法)。
答案 1 :(得分:2)
在不需要时,您不应该先erase
然后再insert
个元素。如果您在迭代器pos
处增加元素,则只需找到插入元素并将元素旋转一个的位置:
auto new_pos = std::lower_bound(pos,end,*pos);
std::rotate(pos,pos+1,new_pos);