在矢量的开头和结尾添加

add at beginning and end of vector

本文关键字:结尾 添加 开头      更新时间:2023-10-16

在向量开头添加向量本身的最后两个元素并在 vetor 末尾添加向量的前两个元素的最聪明方法是什么? 我的意思是,如果我的起始向量是

v = 1 2 3 4 5 6 7 8 9

我需要它变成

v = 8 9 1 2 3 4 5 6 7 8 9 1 2

首先,如果容器要很大,请考虑使用deque而不是vector。在开始时添加更有效。

对于vector,您不能将元素从vector插入到开头,因为发生的第一件事是向量中的所有内容都被移动(并且所有迭代器和对这些元素的引用都无效)。因此,您要么需要将元素从向量中复制出来,要么需要将插入元素放在开头,然后复制分配给它们。假设类型是int,我将选择前者:

if (v.size() >= 2) {
int tmp[] = {*(v.end() - 2), *(v.end() - 1)};
v.insert(v.begin(), tmp, tmp + 2);
tmp[0] = v[2]; tmp[1] = v[3];
v.insert(v.end(), tmp, tmp + 2);
}

或者,这会使用更多内存,但可能更易于阅读。作为奖励,即使对于复制构造函数可以抛出的类型,它也提供了强大的异常保证。我上面的代码可以通过添加对reserve的调用来提供强大的保证,但这只是因为int是一个微不足道的类型:

if (v.size() >= 2) {
std::vector<int> new_v;
new_v.reserve(v.size() + 4);
new_v.insert(new_v.end(), v.end() - 2, v.end());
new_v.insert(new_v.end(), v.begin(), v.end());
new_v.insert(new_v.end(), v.begin(), v.begin() + 2);
v.swap(new_v);
}

对于deque,无需在容器外部存储任何元素,前提是使用引用而不是迭代器来访问它们。同样,这仅提供基本的异常保证。

if (v.size() >= 2) {
v.push_front(v.back());
v.push_front(*&(v.end() - 1));
v.push_back(*&(v.begin() + 2));
v.push_back(*&(v.begin() + 3));
}

我的五分钱

std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
v.insert( v.end(), { v[0], v[1], v[v.size() - 2], v[v.size() - 1] } );
std::rotate( v.begin(), std::prev( v.end(), 2 ), v.end() );
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;

通过使用 vector::insert 函数来表示范围。首先在末尾插入前两个元素更容易。

v.insert(v.end(), v.begin(), v.begin()+2);
v.insert(v.begin(), v.end()-2, v.end());

编辑: 是未定义的行为。

将 std::vector 附加到自身,未定义的行为?