STL进阶--删除元素

删除元素

从vector或deque删除元素

  vector<int> vec = {1, 4, 1, 1, 1, 12, 18, 16}; // 删除所有的1
  for (vector<int>::iterator itr = vec.begin(); itr != vec.end(); ++itr) {
     if ( *itr == 1 ) {
        vec.erase(itr);    //你或许会想到使用erase成员函数
     }
  }   // 的确,是可以达到目的 vec: { 4, 12, 18, 16}
  // 但是复杂度是: O(n*m),每删除一个元素,后面的往前移动

  // 如果使用算法remove
  remove(vec.begin(), vec.end(), 1);  // 复杂度 O(n)
                                      // vec: {4, 12, 18, 16, ?, ?, ?, ?}

  vector<int>::iterator newEnd = remove(vec.begin(), vec.end(), 1);   // 将不删除的元素移到前面,O(n)
  vec.erase(newEnd, vec.end());  //删除最后无用的元素

  // 算法remove_if()和unique()也是类似

  // 此时vec仍然占了8个int空间: vec.capacity() == 8
  vec.shrink_to_fit();   // C++ 11
  // 现在vec.capacity() == 4 

  // For C++ 03:
  vector<int>(vec).swap(vec); // 相同效果,释放空的内存

从List删除

  list<int> mylist = {1, 4, 1, 1, 1, 12, 18, 16};

  list<int>::iterator newEnd = remove(mylist.begin(), mylist.end(), 1);  // 使用算法remove,O(n)
  mylist.erase(newEnd, mylist.end());

  mylist.remove(1);  // 成员函数更快,直接操作指针,从链上删除

从关联容器或无序容器中删除

  multiset<int> myset = {1, 4, 1, 1, 1, 12, 18, 16};

  multiset<int>::iterator newEnd = remove(myset.begin(), myset.end(), 1);  // O(n)
  myset.erase(newEnd, myset.end()); 

  myset.erase(1); // O(log(n)) or O(1)

结论

  • vector或者deque: 算法remove() + erase()
  • list:成员函数remove()
  • 关联容器或者无序容器:成员函数erase()

删除元素之后

// 看个关联容器的例子,此程序会发生什么
multiset<int> s = {1, 4, 1, 1, 1, 12, 18, 16};;

multiset<int>::iterator itr;
for (itr=s.begin(); itr!=s.end(); itr++) {
   if (*itr == 1) {
      s.erase(itr);
      cout << "Erase one item of " << *itr << endl;
   }
}

// 删除第一个元素成功,后面未定义的行为

解决方法:

multiset<int>::iterator itr;
for (itr=s.begin(); itr!=s.end(); ) {
   if (*itr == 1) {
      cout << "Erase one item of " << *itr << endl;
      s.erase(itr++);    //在删除之前,迭代器已经指向下一个
   } else {
      itr++;
   }
}

对于序列容器

vector<int> v = {1, 4, 1, 1, 1, 12, 18, 16};
vector<int>::iterator itr2;
for (itr2=v.begin(); itr2!=v.end(); ) {
   if (*itr2 == 1) {
      cout << "Erase one item of " << *itr2 << endl;
      v.erase(itr2++);    //这样仍然不安全,删除的元素后面的所有迭代器都失效
   } else {
      itr2++;
   }
}

解决方法:

for (itr2=v.begin(); itr2!=v.end(); ) {
   if (*itr2 == 1) {
      cout << "Erase one item of " << *itr2 << endl;
      itr2 = v.erase(itr2);
   } else {
      itr2++;
   }
}

// 1 序列容器和无序容器的erase返回指向删除元素下一个元素的迭代器
// 2. 关联容器的erase不返回东西

总结

  • 序列容器和无序容器使用:it = c.erase(it);
  • 关联容器:c.erase(it++);

使用算法

vector<int> c = {1, 4, 1, 1, 1, 12, 18, 16};

//普通函数
bool equalOne(int e) {
   if (e == 1) {
      cout << e << " will be removed" << endl;
      return true;
   }
   return false;
}
auto itr = remove_if(c.begin(), c.end(), equalOne);
c.erase(itr, c.end());

//使用bind():
bool equalOne(int e, int pattern) {
   if (e == pattern) {
      cout << e << " will be removed" << endl;
      return true;
   }
   return false;
}
remove_if(v.begin(), v.end(), bind(equalOne, placeholders::_1, 1));

// Lambda函数:
auto itr = remove_if(v.begin(), v.end(),
      [](int e){
         if(e == 1) {
            cout << e << " will be removed" <<endl; return true;
         }
      }
   );

原文地址:https://www.cnblogs.com/logchen/p/10205623.html

时间: 2024-10-29 03:19:33

STL进阶--删除元素的相关文章

STL容器删除元素的陷阱

今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector<struct> mFriendList;...std::vector<struct>::iterator iter = mFriendList.begin();for ( ; iter != mFriendList.end(); ++iter){    if (...)        mFr

坑 - stl之删除元素

概述 stl中删除元素,会使用到erase或remove,erase一般用于删除一个或者一段范围内的元素,而remove则可以删除指定值的所有元素.但是在使用remove时会有一些需要注意的地方,不细心的话容易掉坑里,故记录在此. remove的原型 template <class ForwardIterator, class T> ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T&

STL容器遍历时删除元素

STL容器遍历时在循环体内删除元素最容易出错了,根本原因都是因为迭代器有效性问题,在此记下通用删除方法,该方法适用于所有容器: 1 std::vector<int> myvec; 2 3 std::vector<int>::iterator it = myvec.begin(); 4 while( it != myvec.end()) 5 { 6 it = myvec.erase(it); 7 } 容器list有个比较另类的删除方法,如下代码所示: std::list<int

STL中用erase()方法遍历删除元素?.xml

pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9;font-style:italic;font-weight:bold;} .selfFuc{color:#f1f9be;} .bool{color:#69305e;} .condition{color:#628698;font-weight:bold;} .key{color:#e336b6;} .

STL中慎重选择删除元素的方法

 一.要删除容器中有特定值的所有对象 1.如果容器是vector.string或deque,则使用erase-remove习惯用法.例如: vector<int> c; c.erase(remove(c.begin(),c.end(),1963),c.end());//删除值是1963的元素 下面讲一下算法remove: template<classForwardIterator,class T> ForwardIteratorremove(ForwardIterator fi

STL 中 使用迭代器删除元素的问题

在vector中删除,大家都知道,直接erase的话,这种写法很有问题.因为erase(iter)之后iter指针就变成野指针了,此时继续iter++就会出问题. 1 for(auto iter = v.begin(), iter!=v.end(); iter++) 2 { 3 if(iter == 3) 4 v.erase(iter); 5 } 因此vector中正确的删除的方法是: for(auto iter = v.begin(), iter!=v.end(); /*iter++*/) {

STL容器之 元素删除

stl容器的元素删除跟具体的按内存分配方式关系密切.按内存分配方式可以分为节点内存容器和连续内存容器. 节点内存容器指的是一种表现方式,包括list.slist等这样基于节点的容器(链表实现)和set.map.multiset.multimap等关联容器(平衡树实现) 连续内存容器指的是在一块连续的内存上保存元素的连续内存容器,比如vector等. 1.节点内存容器 以list为例,当调用erase函数之后,被删除的元素的迭代器将会失效,则需要在删除之前移动迭代器,并传入原来迭代器的拷贝作为er

怎么删除STL容器的元素

在STL容器有顺序容器和关联容器两种. 顺序容器删除元素的方法有两种: 1.c.erase(p) 从c中删除迭代器p指定的元素.p必须指向c中一个真实元素,不能等于c.end().返回一个指向p之后元素的迭代器,若p指向c中的尾元素,则返回c.end() 2.3.c.erase(b,e) 删除迭代器对b和e所代表的范围中的元素.返回e 关联容器删除元素的方法有三种: 1.c.erase(k) 从c中删除每一个关键字为k的元素.返回一个size_type值,指出删除的元素的数量. 2.c.eras

STL——遍历 删除 set 元素

==================================声明================================== 本文版权归作者所有. 本文原创,转载必须在正文中显要地注明作者和出处,并保证文章(包括本声明)的完整性. 未经作者授权请勿修改(包括本声明),保留法律追究的权利. 未经作者授权请勿用于学术性引用. 未经作者授权请勿用于商业出版.商业印刷.商业引用以及其他商业用途. 本文不定期修正完善,为保证内容正确,建议移步原文处阅读. 本文链接:http://www.c