【问题标题】:Is erase() in std::vector linear time operation?是 std::vector 线性时间操作中的擦除()吗?
【发布时间】:2016-10-01 22:08:04
【问题描述】:

页面http://www.cplusplus.com/reference/vector/vector/erase/

与擦除(破坏)的元素数量加上数量成线性关系 在最后一个元素被删除(移动)之后的元素。

所以,如果我要删除一个元素,比如说,从某个长度的向量 j 中删除一个元素 n (n>j) - 它是恒定的还是线性的(O(n))?

或者,如果我在 Jth 元素之后有 p 元素,那么它将是有序的 O(p) - 我说的对吗?

【问题讨论】:

  • 其实你贴的链接里已经说过复杂度是线性的。
  • 所以如果我在第 J 个元素之后有 p 元素,那么它将是 O(p) 的顺序,对吗??
  • 它将是 theta(p)...

标签: c++ vector erase


【解决方案1】:

我在这里了解到,标准是最好的参考。

来自23.3.11.1/1[vector.overview]:

向量是一个序列容器,它支持(摊销)最后的恒定时间插入和擦除操作;在中间插入和擦除需要线性时间。

因此,在这种情况下,erase 既不是常数也不是线性时间。
这主要取决于您执行的操作类型:

  • 如果您在矢量末尾擦除它是恒定的,
  • 否则是线性的。

【讨论】:

    【解决方案2】:

    从您提供的链接:

    与擦除(破坏)的元素数量加上数量成线性关系 删除最后一个元素后的元素数(移动)

    这意味着当从std::vector 中删除 N=1 个元素时。在您的情况下,它将对等于 1 的析构函数进行 N 调用。然后它将使 M 移动操作等于 (n-j-1) 在您的情况下。所以它是线性的而不是常数。

    所以 std::vector::erase 的复杂性是:O(Deleted_Items_Count) + O(Moved_Items_Count)

    在你的情况下:1*Destructor_Time + (n-j-1)*Moving_Time


    为了在恒定时间内从向量中擦除项目,您可以从向量的尾部擦除它们(例如std::vector::pop_back

    所以如果你想要一个恒定的时间擦除而不用排序:

    auto linear_erase=[](auto& v, const size_t index){
        std::swap(v[index], v.back());
        v.pop_back();
    };
    

    【讨论】:

      【解决方案3】:

      从向量中删除N元素将花费O(N)的时间复杂度,因为应用程序必须遍历M元素,并调用每个元素的析构函数,然后将其余元素复制到创建的间隙通过破坏被擦除的元素。

      因此,如果我们有一个带有 N 元素的向量,并且我们从范围 (p,q] 中删除元素,那么销毁该范围将花费 O(q-p) 时间复杂度,您可以说是 O(1),因为pq 是常量。那么您将不得不复制/移动范围 (q,N] 。因为N-q是线性的,所以时间复杂度是O(N)

      我们一起得到O(N) + O(1) = O(N)

      当然,如果删除以数组末尾结尾的范围,则复杂度为O(1),因为没有要复制/移动的元素。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-17
        • 2018-12-05
        • 2011-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-24
        相关资源
        最近更新 更多