注意C++ STL容器中erase的使用

 

erase()函数的功能是用来删除容器中的元素
注意C++ STL容器中erase的使用 - mirali - 小玉 的博客 函数原型:
注意C++ STL容器中erase的使用 - mirali - 小玉 的博客iterator erase(iterator where);
注意C++ STL容器中erase的使用 - mirali - 小玉 的博客iterator erase(iterator first,iterator last);
注意C++ STL容器中erase的使用 - mirali - 小玉 的博客basic_string
&  erase(size_type p0 = 0 ,size_type n = np);


删除某个容器里的某个元素:c.erase(T);
看似一个简单的动作,然而对不同类型的容器,内部却做了截然不同的事情,后面介绍。

假设有这样一个题目,将某个容器中所有满足条件N == X的元素删除,按照常规的思路应该有类似这样的代码:

//  假设Container和container分别表示一种容器和对应的一个对象
Container < T > ::iterator it;
for  (it  =  container.begin(); it  !=  container.end();  ++ it) {
  
if  (N  ==  X)
    container.erase(it);
}


然而这样的代码对于任一种容器都是错误的注意C++ STL容器中erase的使用 - mirali - 小玉 的博客
容器按内存分配方式可以分为链表容器和数组容器。
所谓的链表容器指的是一种表现方式,包括list、slist等这样基于节点的容器(动态分配内存块)和set、map、multiset、multimap等关联容器(平衡树实现),而数组容器指的是在一块连续的内存上保存元素的连续内存容器,比如vector、deque、string等。

OK,现在说说erase对他们的操作,链表容器以list为例,当执行container.erase(it)时,确实第一个满足条件的元素删除了,但这时it指针已经被删除了,它也不指向任何元素了,所以也只能到此为止了,也就是说上面的代码对于链表容器来说只能正确删除第一个满足条件的元素,针对这个问题我们首先想到的就是在删除指针之前,给其做个备份,很好,不错的主意,我们一般采用的方法是建立个临时变量,这个临时变量可以在程序循环中适当的位置使用,看下列代码实现,是将这个临时变量直接建立在erase实现里,这样做更简洁,也显得专业些注意C++ STL容器中erase的使用 - mirali - 小玉 的博客(以删除int型链表中所有偶数为例,也是大家都喜欢的一个例子):

  list < int > ::iterator it; 
  
for  (it  =  lt.begin(); it  !=  lt.end(); ) {
    
if  ( * it  %   2   ==   0 )
      lt.erase(it
++ );
    
else
      
++ it;
  }

链表容器使用erase删除节点还有一个特点,就是会将下一个元素的地址返回,所以也可以这样实现:

  list < int > ::iterator it; 
  
for  (it  =  lt.begin(); it  !=  lt.end(); ) {
    
if  ( * it  %   2   ==   0 )
      it 
=  lt.erase(it);
    
else
      
++ it;
  }


当然用list容器本身提供的算法也是个不错的主意(挂回调):

   bool  evenNumber( int  n)
  {
    
return  (n  %   2   ==   0 );
  }
  
  注意C++ STL容器中erase的使用 - mirali - 小玉 的博客注意C++ STL容器中erase的使用 - mirali - 小玉 的博客
  
  lt.remove_if(evenNumber);


数组容器以vector为例,当执行container.erase(it)时,和上面提到的一样,第一个满足条件的元素删除了,但这时数组容器不允许中间有“空隙”,所以会做个大动作,就是将被删元素后面所有的元素前移(参考STL源码),而数组容器记录的是下标,所以删除元素后,当前下标定位的元素也就顺理成章的变成了原有队列中的下一个元素,同样以删除偶数为例,代码如下:

  vector < int > ::iterator it  =  v.begin();
  
for  (it  =  v.begin(); it  !=  v.end(); ) { 
    
if  ( * it  %   2   ==   0 )
      v.erase(it);
    
else
      
++ it;
  }

也可以使用reverse_iterator迭代器,并且在某些删除操作中会有更好的效率(因为它会使上面提到的“大动作”变小一些):

  vector < int > ::reverse_iterator ri  =  v.rbegin();
  
for  ( ; ri  !=  v.rend(); ) { 
    
if  ( * ri  %   2   ==   0
      v.erase((
++ ri). base ());
    
else  
      
++ ri;
  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值