我需要一个容器,允许我在循环时快速擦除 ONE 元素。我不需要直接访问,因为我总是在循环中访问它。
对于这种情况,List
是否比Vector
更快?
伪代码:
vector<Item*> myContainer;
for(..loop over it...) {
if (someCondition)
myContainer.erase(currentElement)
}
删除元素后,我需要保持循环覆盖其余元素
答案 0 :(得分:6)
是的,理论列表提供了比矢量更快的删除,但在实践中,没有人使用列表。为什么不?因为向量生成的堆活动少得多,并且它们提供了更好的缓存局部性。
你确定你绝对需要逐个遍历矢量并擦除元素吗?这将导致向量的二次复杂度,但erase-remove-idiom在线性时间内完成:
#include <algorithm>
myContainer.erase(
std::remove_if(
myContainer.begin(),
myContainer.end(),
[](Item* p) {
return p->someCondition;
}
),
myContainer.end()
);
(如果向量拥有Items,您应该用vector<unique_ptr<Item>>
替换它。)
作为替代方案,如果你真的必须逐个删除元素,并且你不关心Items的相对顺序,那么有一个neat little trick可以在恒定时间内删除一个向量的元素
答案 1 :(得分:5)
使用列表删除任意位置的元素更快:
Complexity of std::vector::erase:删除的元素数量(析构函数)加上最后一个元素删除(移动)后的元素数量。
Complexity of std::list::erase:删除的元素数量(析构函数)线性。
此外,擦除后迭代器将无效,因此您需要更新迭代器:
it = list.erase(it);
答案 2 :(得分:0)
c ++列表是一个链表。所以元素将按如下方式排列,
head <--> 1 <--> 2 <--> 3 <--> 4 <--> 5
所以,当我想删除3时,它只是一个指针改组。我想要擦除3,我需要移动2的指针指向4.在这种情况下,我需要移动到3(发现元素)。时间复杂度将是O(1)最坏情况,因为它是双向链表并且您已经指向要删除的元素。
然而另一方面,c ++向量只是一个数组。因此,在从数组中删除元素之后,移除向量元素。在这种情况下,您可以在O(1)复杂度中发现要擦除的元素。但要删除它,您需要左移所有元素以移除创建的空白。因此,复杂性是O(n)最坏的情况。从口头上讲,复杂性可能类似于“n - 要删除的元素索引”。
列表产生O(1)和向量O(n)渐近的删除复杂度。但是该列表将为每个元素维护指针(总计额外的O(2n)空间)带来额外的开销。