创建std :: vector减去一个元素的副本的最快方法
fastest way to create a copy of a std::vector minus one element
我有一个std :: vector [1,2,3,4,5],我想获得另一个载体,其中包含所有元素,但第二个元素:[1,3,3,4,5]。一种方法是(VEC1是我的输入向量):
std::vector<int> vec2;
vec2 = vec1;
vec2.erase(vec2.begin()+1)
在这里,我真的不喜欢o(n)复杂性的擦除,因此考虑到阵列的副本,我将拥有2N操作。我在想旧的虚拟方法会更好:
std::vector<int> vec2;
for(int i=0; i<vec1.size(); ++i){
if (i != 1)
vec2.push_back(vec1[i]);
}
这是摊销的O(n)时间。渐近行为是相同的,但操作数量可能较小。
我必须在相当小的矢量(约100个元素)上执行此操作,但是我有数十亿。我会注意到有很大的区别吗?
您将如何做?
关于复杂性,您不能比O(n)更好,因为您必须复制n个元素。但是出于某些微观化的目的,您可以:
- 保留先验的规模,如评论
-
避免通过连续2个副本进行循环内检查条件,但没有检查:
std::vector<int> vec1 = { 1,2,3,4,5 }; std::vector<int> vec2(vec1.size()-1); constexpr int i = 1; // let i be the position you want to skip std::copy(vec1.cbegin(), vec1.cbegin() + i, vec2.begin()); std::copy(vec1.cbegin() + i+1, vec1.cend(), vec2.begin()+i);
由于没有if
语句或std::copy-if
,这些副本将很简单,而且编译器优化的良好空间。
编辑:如下评论中,调整向量的调整会引起一些初始化的其他初始化,请参阅此处避免启动的方法的讨论:使用vector&lt; char&gt;作为缓冲区,而无需在resize()
可以使用std::vector
的现有例程完成。给定i
,这是您要跳过的位置(在vec
的范围内):
template<typename T>
vector<T> skip_copy(const vector<T> &vec, size_t i)
{
vector<T> ret;
ret.reserve(vec.size() - 1);
ret.insert(ret.end(), vec.begin(), vec.begin() + i);
ret.insert(ret.end(), vec.begin() + i + 1, vec.end());
return ret;
}
通过保留空间,我们避免了ret
中的任何不必要的内存分配。和vector::insert
在最后完成时,无需转移元素。
授予,insert
可能会做一些额外的条件,而不是严格需要的(检查迭代器范围是否适合现有存储中),但是一系列push_back
调用的速度不太可能更快。并且如果vector
的大小很重要,则不必预先确定数组的付费。
这是我想到的最快方法:
std::vector<int> vec1{1, 2, 3, 4, 5};
// Do not call the constructor with the known size here. That would allocate
// AND initialize a lot of data that will be overwritten later anyway.
std::vector<int> vec2;
// Instead, use it on 'reserve' since it only allocates the memory and
// leaves it uninitialized. The vector is still considered empty, but its
// underlying capacity will be big enough to be filled with new data
// without any unnecessary initializations and reallocations occuring (as long
// as you don't exceed the capacity)
vec2.reserve(vec1.size() - 1);
// Nothing expensive should be going on behind the scenes now, just fill it up
for(auto it = vec1.begin(), skip = vec1.begin() + 1 ; it != vec1.end() ; ++it) {
if(it != skip) {
vec2.push_back(*it);
}
}
相关文章:
- lower_bound()返回最后一个元素
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 使用运算符 [] 引用 std::vector 上最后一个元素时出现问题<>
- Lower_bound不适用于具有 3 个元素的向量的最后一个元素
- 检查 2D 网格的某个元素是否与另一个元素共享对角线、水平线或垂直线
- 仅显示链表的最后一个元素
- push_back通过自行创建的对象获取最后一个元素的向量
- 使用 map.end() 访问 map 的最后一个元素
- 如何知道地图中的最后一个元素是否被删除?
- 选择一个元素而不是一个对象的数组的原因
- std::矢量保存 只推送最后一个元素
- 为什么这个选择排序算法仍然切换一个元素,当它已经是其他元素中最小的元素时?
- 反转后不返回最后一个元素
- 如何在新数组较小时创建新数组并将旧数组的最后一个元素复制到新数组中?
- 访问 for_each 函数中的前一个元素
- 在 QListView 中显示最后一个元素
- 从 std::vector 中选择一个元素,而不是给定元素
- C++:在进行切片时对迭代器的约定,特别是对于访问最后一个元素并最终将其删除
- 遍历列表包含排除最后一个元素的内容
- 如何从一个无序集合中获取一个元素