STL矢量元素去除效率
STL vector element removal efficiency
我有一个对象向量。所有对象元素都是唯一的。为类的唯一id定义函子。
从vector
中删除object元素会更有效吗?myvec.erase(std::remove_if(myvec.begin(), myvec.end(), MyClass(id)), myvec.end());
//OR
itonmyvec = std::find_if(myvec.begin(), myvec.end(), MyClass(id));
if(itonmyvec != myvec.end())
myvec.erase(itonmyvec);
实际最快的方法两者都不是。两者都受到标准中附加的约束,即保持剩余元素的相对顺序,但这不是您所要求的。
因此,最快的解决方案是- 查找元素
- 与最后一个元素交换
- 删除新的最后一个元素。
执行O(1)个赋值,而不是O(N)个。
由于您使用的是矢量,因此两种建议的实现几乎是相同的。
第一个将遍历vector一次,同时测试每个元素并压缩vector,然后最后析构最后一个元素并缩短vector。
第二个操作遍历vector对象,直到找到该元素,然后遍历vector对象的其余部分进行压缩并最终缩短vector对象。
事实证明,两个版本之间唯一真正的区别是,第二个版本将能够平均节省O(n/2)个比较。如果比较便宜,性能将更多地取决于系统的其他属性,例如,哪个实现对缓存更友好。
因此,最后的答案只能是基准测试吧!注::第一个版本必须检查remove_if
的结果是否与向量的end
完全相等,以便在两个版本中以相同的方式进行检查(或不进行检查)
Docs for remove_if say
当find_if被指定为 时从范围中删除所有满足特定条件的元素…
返回范围内的第一个元素…
既然知道vector中的所有元素都是唯一的,那么可以在第一次匹配之后安全地停止搜索。这意味着对于这种特定情况,第二种形式可能更快。
还请注意,如注释中所述,第一种方法是错误的。remove_if
返回一个迭代器到(可能更新的)范围的末端。你不希望从你的矢量中删除它——它保证不匹配你的目标值。
对于MSalters给出的答案,我已经写下了代码。我无法将代码添加到答案的注释中,所以添加到新答案中。希望这对你有帮助!
//Remove 3rd element
vector<int> v {1,2,3,4,5}; //C++11 compiler needed!
vector<int>::iterator it1 = find(v.begin(), v.end(), 3);
vector<int>::iterator it2 = --v.end();
std::swap(*it1, *it2);
v.pop_back();
如果您愿意牺牲异常安全性,那么您可以比当前接受的答案做得更好:而不是与最后一个元素交换然后调用pop_back()
,您可以简单地用最后一个元素覆盖要删除的元素。你必须向后迭代,从最后一个元素开始。
如果您使用的是整数,那么这很好,而且很可能节省大量时间。如果你使用的是谁也不知道会抛出移动拷贝的类,那么你就有麻烦了,你的异常安全保证也就完了。
下面是一个示例代码:#include <iostream>
#include <vector>
template <typename Vector, typename Pred>
void remove(Vector& v, Pred p) {
auto last(v.rbegin());
for (auto pos(last), rend(v.rend()); pos!=rend; ++pos) {
if (p(*pos))
// overwrite the element to be removed with the currently last element
*pos = std::move(*last++);
}
v.erase(last.base(), v.end());
}
// pretty print the vector for debugging
template <typename Vector>
void show(const Vector& v) {
std::cout << "{ ";
auto pos(v.begin());
auto last(v.end());
if (pos!=last) {
--last;
while (pos!=last)
std::cout << *pos++ << ", ";
std::cout << *last;
}
std::cout << " }" << std::endl;
}
// a simple-minded test that removes all 2s from the vector
void remove_2s(std::initializer_list<int> l) {
auto equals_two = [](int i) { return i==2;};
std::vector<int> v{l};
remove(v, equals_two);
show(v);
}
int main() {
remove_2s({1, 2, 3, 2, 5, 7, 4, 2, 6});
remove_2s({ 1, 2 });
remove_2s({ 2, 1 });
remove_2s({ 2 });
remove_2s({ 2, 2 });
remove_2s({ });
remove_2s({ 1 });
}
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 使用strcpy将char数组的元素复制到另一个数组
- 使用不带参数的函数访问结构元素
- 给定n个元素的m个集合.在C++中找到出现在最大集合数中的元素
- C++如何通过用户输入删除列表元素
- lower_bound()返回最后一个元素
- 基于多个条件处理地图中的所有元素
- 调整大小后指向元素值的指针unordered_map有效?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 使用函数"remove"删除重复元素
- 具有最大子序列大小的序列,每个元素都相同
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 如何将元素添加到数组的线程安全函数?
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- 首先创建字符串,然后通过移动语义将其添加到 vector 或在 vector 中创建元素是否具有内存效率
- 为什么快速排序在有许多重复元素的情况下效率低下
- 在添加元素的同时提高向量的效率
- STL矢量元素去除效率
- 读取CAN输入时更新GUI元素的效率/速度