列表与矢量,循环时删除元素

时间:2012-07-22 09:40:24

标签: c++ performance list vector

我需要一个容器,允许我在循环时快速擦除 ONE 元素。我不需要直接访问,因为我总是在循环中访问它。

对于这种情况,List是否比Vector更快?

伪代码:

vector<Item*> myContainer;

for(..loop over it...) {

  if (someCondition)
    myContainer.erase(currentElement)
}

删除元素后,我需要保持循环覆盖其余元素

3 个答案:

答案 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)空间)带来额外的开销。