反向迭代器reverse_iterator与正向迭代器iterator之间的转换(list反向删除元素的方法)
2017-07-05 23:01
459 查看
首先,本文的公众号地址为:你真的会清理std::list的元素吗? 转载请注明出处,谢谢!有经验的程序员都知道,list是链表,可以遍历删除,删除的过程类似于以下代码(遍历删除521):int key=521;//程序员就不要爱情了吧
list<int>::iterator it=l.begin();//l为std::list<int>
for (; it != l.end();)
{
if (key== *it) {
it = l.erase(it);
}
else {
++it;
}
}
这是我们通常使用的删除方法,我们现在有一种场景:
公司为了惩罚员工迟到(我瞎说的,迟到了是要扣工资的。工作实际遇到的场景描述过于复杂),对于某一天的迟到的员工进行处罚,并且,由于有些员工是,年龄大了,网开一面,就不惩罚了。
假设我们的员工打开记录都存放在一个list里面,按照时间顺序存放,来的晚的打卡记录就在后面。
定义打卡的结构体:
struct DingDong
{
long id;//员工id
long time;//打卡时间
int age;//员工年龄,人性化考虑,大于45岁的员工不处罚
};
信息定义:
typedef std::list<DingDong> DingDongList;
DingDongList dd_list;///全部员工打开记录
DingDongList punish_list;//惩罚员工名单
long normal_time = 90000;//正常上班时间
int normal_avg = 45;//惩罚的年龄上限,包含45岁
员工的打卡记录类似于:
场景描述完毕,我们开始处理
我们是个大厂子,有个10万的员工(我们不是鹅厂的,场景纯属虚构),
每天迟到的可能就100到200,从头开始遍历,很不明智,于是我们逆序遍历,并且,90000上班(9:00:00),大于45岁不处罚,代码如下
DingDongList::reverse_iterator r_iter = dd_list.rbegin();
for (; r_iter != dd_list.rend();)
{
if (r_iter->time <= normal_time) break;//迟到的员工都找到了
if (r_iter->age<=45)
{
punish_list.push_back(*r_iter);
//删掉该节点
}
else
{
++r_iter;
}
}
//punish_list拿去惩罚吧,dd_list剩下的员工都是好同志(45岁以上迟到的老人也算是好同志)。
看到了“删除该节点"位置,该怎么删掉该节点呢。通过查询,我们发现list的erase()方法的参数只有如下几种,并没有对反向迭代器的删除操作:
那怎么办呢?难道就无法删除反向迭代器的元素了?
通过分析STL的iterator和reverse_iterator源码实现,发现了一些东西:
首先是,反向迭代器是继承迭代器的
反向迭代器的求值操作求的是 (*(--current)),即当前存储迭代器的前一个迭代器的值。
->操作则是求*操作后,求地址。
这些事实说明,reverse_iterator的求值和->操作都返回的是--iterator位置的数据。或者说,当前反向迭代器里面的指针指向的是,所访问的元素的下一个元素。
怎么把reverse_iterator转换成iterator呢?毕竟erase()能够删除的是iterator。
经过查证,发现了
那么,base()方法求到的是
实际上我们要删除的是元素5,那么求出指向5的正向迭代器呢?
分析代码我们知道,反向迭代器的++操作是指针往前挪动,即++rbegin()之后,reverse_iterator内部存储的指针就指向了元素5,然后求一下base()就是指向5的正向迭代器了(++rbegin()).base();
那么,逆序删除list元素的过程就呼之欲出了吧,放代码:
DingDongList::reverse_iterator r_iter = dd_list.rbegin();
for (; r_iter != dd_list.rend();)
{
if (r_iter->time <= normal_time) break;//迟到的员工都找到了
if (r_iter->age <= 45)
{
punish_list.push_back(*r_iter);
r_iter = DingDongList::reverse_iterator(dd_list.erase((++r_iter).base()));
}
else
{
++r_iter;
}
}
到此,利用反向迭代器删除某些元素的功能就完成了。迟到的年轻员工,等着扣工资吧
本文提到的reverse_iterator的实在/usr/include/c++/4.4.7/bits/stl_iterator.h文件中,当然,因为gcc版本的不同4.4.7这个路径可能是4.8.5或者4.8.2,有兴趣的话可以自己拿到源码分析一下,就一目了然了.
相关文章推荐
- 遍历list时删除某些情况下的元素,使用迭代器Iterator
- 集合框架(一)续 向集合中添加一个集合、数组和List之间的相互转换、从集合中删除另一个集合所包含的元素
- stl容器用反向迭代器连续删除元素的方法
- 关于STL的list,vector等用迭代器iterator,用erase删除元素出现的问题。
- 关于STL的list,vector等用迭代器iterator,用erase删除元素出现的问题。
- set容器元素的插入和中序遍历,反向遍历,反向迭代器reverse_iterator和rbegin(),rend();
- STL中迭代器失效——用erase()方法遍历删除元素
- 关于数组和List之间相互转换的方法
- 如何使用迭代器iterator循环删除容器中的元素?
- 关于数组和List之间相互转换的方法
- 使用Iterator的remove方法删除元素
- [java]关于数组和List之间相互转换的方法
- 关于数组和List之间相互转换的方法
- 关于数组和List之间相互转换的方法
- 反向思维的妙处---解决正向循环删除元素的问题
- 【STL】反向迭代器(Reverse Iterator)
- 关于数组和List之间相互转换的方法
- 数组和List之间相互转换的方法
- ArrayList利用迭代器Iterator遍历方法实现数据(新闻)的删除、添加、显示功能例子
- C++语法基础--泛型算法(generic algorithm)--反向迭代器,reverse_iterator::base()