删除算法选择

使用remove 删除
对于连续内存容器(vector,deque,string)最好的方法使用erase-remove方法。

比如对于

std::vector<std::string>words{"one","none","some","all”,"none","most","many"};

remove()算法由定义在algorithm头文件中的模板生成,它可以删除匹配特定值的一段元素

auto iter=std::remove(std::begin(words),std::end(words),"none");

头两个参数指定的元素范围内,移除了所有匹配remove()的第三个参数string("none")的元素。移除元素这个表述有一点误导,remove()是一个全局函数,所以它不能删除容器中的元素。remove()移除元素的方式和从字符串中移除空格的方式相似,都是通过用匹配元素右边的元素来覆盖匹配元素的方式移除元素。下图展示了这个过程:

如果在remove()操作后输出words中的元素,只会输出前5个元素。尽管size()返回的值仍然是7,而且最后两个元素仍然存在,但是它们被替换成了空字符串对象。为了摆脱这些多余的元素,可以使用成员函数erase()。remove()返回的迭代器可以这样使用:

words.erase(iter,std::end(words));

这被叫作erase-remove,执行删除操作后,iter指向最后一个元素之后的位置,所以它标识了被删除序列的第一个元素,被删除序列的结束位置由std::end(words)指定。当然,在一条语句中,也能先移除元素,然后再删除末尾不想要的元素:

words.erase(std::remove(words.begin(),words.end(),"none"),words.end());

对于list和 forward_list:erase_remove同样有效,但是使用list的成员函数remove()更高效。

C.remove(“none”);

使用remove_if 条件删除
对于连续内存容器需要条件删除时:将remove替换为remove_if.

bool IsMove(string)

{ ...}

words.erase(std::remove_if(words.begin(),words.end(),IsMove),words.end());

对于list和 forward_list当需要条件删除时:将remove替换为remove_if.

C.remove_if(IsMove);

使用erase 删除
需要使用到成员函数erase:

序列容器有两种重载函数:

移除位于pos的元素;
移除范围[first;last)中的元素。
关联容器有三种种重载函数:

移除位于pos的元素。
移除范围[first;last)中的元素。
移除关键等于key的元素(若存在一个)
可以看出关联容器中的erase可以删除特定值的元素。事实上关联容器用这种删除效率最高。还有一种间接的做法是:使用remove_copy_if和swap配合使用,利用remove_copy_if将原始容器中保留的元素copy到一个新容器中,然后再将新容器swap到原始容器中,但效率低,不推荐。

回头来看关联容器产出特定值元素的操作:

函数size_type erase(const key_type&key) 移除键值等于key的元素(若存在一个)。条件删除时使用下面的方法。

但是上面的代码有问题,迭代在容器改变时会出现失效的风险。使用下面的方式删除迭代器。

C++11,提供了统一的操作iter=cTest.erase(iter),需要利用erase并返回被删除元素的下一个元素的有效迭代器。

对于关联容器和list:cTest.erase(iter++)也可以,iter先传给erase,然后指向下一个元素,完了再删除。为了统一不建议怎么干。

对于forward_list: 需要换成erase_after。删除下一个元素并返回被删除元素的下一个元素。

要删除B,则应该传入A的迭代器,返回的是C的迭代器。

结论:
对于关联容器:
删除某个key值的所有元素,可以使用size_type erase(const key_type&key);

删除特定的操作,写一个循环,并使用它的erase成员函数删除迭代器。推荐iter=cTest.erase(iter)。

对于连续内存容器:
删除特定值的所有对象选用erase-remove;

删除容器中满足特定条件的所有对象使用erase-remove_if;

除了删除还有其他操作则使用循环,并使用它的erase成员函数删除迭代器。iter=cTest.erase(iter);

对于链表:
删除特定值的所有对象选用成员函数remove;

删除容器中满足特定条件的所有对象使用成员函数remove_if;

除了删除还有其他操作则使用循环,并使用它的erase成员函数删除迭代器。推荐iter=cTest.erase(iter);forward_list需要换成erase_after。
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

u010787096

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值