【问题标题】:Can vector erase() function delete two consecutive same elements?矢量擦除()函数可以删除两个连续的相同元素吗?
【发布时间】:2021-06-10 06:50:28
【问题描述】:

下面是我的程序的 sn-p。我遍历一个向量并尝试删除所有具有 三的值。但是我打印出向量的内容后,是1-2-4-3-5,还是有数字3,为什么?如果要删除两个连续相同的元素,是否需要专门处理迭代器?

int main()
{
    std::vector<int> a = {1, 2, 3, 4, 3, 3, 5}; // a has size 5
    for(auto it=a.begin();it!=a.end();)
    {
        if(*it == 3) it=a.erase(it);
        it++;
    }
    for(auto x:a) cout<<x<<endl;
}

【问题讨论】:

  • 在迭代容器时不要删除元素。使用erase-remove-idiom
  • erase 函数真的会返回您期望的迭代器吗? (提示:它没有)
  • 而在您的情况下,也许更好的解决方案是调用std::remove?但是你还必须了解the erase-remove idiom
  • 这是坏了。盲增量无法考虑it=a.erase(it) 在列表的最后一个 元素上触发,并因此将it 降落在a.end() 上。如果发生这种情况(例如:a = { 1,2,3,3 } ),随后的无条件 it++ 将调用 未定义的行为,正如我们在您的 previous post on this code 中多次说过的那样。由于该问题中所述的原因,这与在循环的增量步骤中有 it++ 一样被破坏

标签: c++ vector stl duplicates erase


【解决方案1】:

我们可以分解你的例子,只看最后三个数字3, 3, 5

擦除前 3 后,返回第二个 3 的迭代器二

it = a.erase(it);

但在此it 之后立即递增

it++;

现在指向 5。


在这里您可以使用erase-remove-idiom。示例代码:

a.erase(std::remove(a.begin(), a.end(), 3), a.end());

【讨论】:

    【解决方案2】:

    &lt;algorithm&gt; 中有一个名为remove_if(first, last, func) 的方法可以解决您的目的。它更安全。请检查以下代码被剪断-

    #include <iostream>
    #include <vector>
    #include <algorithm>
    bool isThree(int k){
       return (k == 3);
    }
    
    int main(){
    
      std::vector<int> v {1,2,3,4,5,6,7,3,3,3};
      std::vector<int>::iterator it;
      
      v.erase(std::remove_if(v.begin(), v.end(), isThree), v.end());
    
      for(int i=0;i<v.size(); i++){
         std::cout << v[i] << " ";
      }
    
      return 0;
    }
    

    【讨论】:

      【解决方案3】:

      错误是每次删除元素时都会跳过检查元素。这是因为it = a.erase(it); 将所有元素向后移动超过it 并返回it - 要解决此问题,请不要在擦除时增加it

      for(auto it=a.begin();it!=a.end();)
      {
          if(*x == 3) it=a.erase(it); else it++;
      }
      

      此外,此代码很慢,因为它可能是 o(n^2) 操作 - 您最好使用 std::remove 然后触发擦除/调整大小以使您的向量具有正确的大小。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-10
        • 2020-02-29
        • 1970-01-01
        • 1970-01-01
        • 2017-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多