STL的remove函数和list的remove成员函数
2016-03-30 20:02
267 查看
算法就是一个个的函数,通过迭代器和容器关联在一起,完成一些工作。
算法和容器的分离为程序设计提供了很大的灵活性,但是也带来了一些负面效果,下面我讲的这个问题就是一个例子。
STL的算法里有一个remove函数,而list自身也有一个remove函数,功能都是一样的,移除某一个元素,那我们应该使用哪一个呢?
看一下下面这段程序
1 list<int> numbers; 2 3 for ( int number = 0; number <= 6; number ++ ) { 4 numbers.push_front(number); 5 numbers.push_back(number); 6 } 7 8 copy(numbers.begin(), numbers.end(), 9 ostream_iterator<int>(cout, " ")); 10 cout << endl; 11 12 // remove algorithm will remove element but not erase the element from container 13 // it will return the logical desination of container 14 list<int>::iterator endOfNumbers = remove(numbers.begin(), numbers.end(), 3); 15 16 copy(numbers.begin(), numbers.end(), 17 ostream_iterator<int>(cout, " ")); 18 cout << endl;
输出是什么呢?
第一行肯定是6 5 4 3 2 1 0 0 1 2 3 4 5 6,那么第二行会输出什么?
如果是没有仔细看过STL的人肯定会认为remove(number.begin(), numbers.end(), 3)会移除所有值为3的元素。所以输出是:6 5 4 2 1 0 0 1 2 4 5 6。
但是,我们看一下它真正的输出:
6 5 4 2 1 0 0 1 2 4 5 6 5 6
你可能会非常惊讶,为什么最后会多出5和6两个数呢?
我们来讲一下remove算法的原理。
remove算法工作时并不是直接把元素删除,而是用后面的元素替代前面的元素,也即是说如果我对1234这个序列remove 2,返回的序列是 1344(3被复制到2的位置,4被复制到3的位置)。
这样上面的例子就好解释了,那两个3的元素并没有被移除,而是用后面的元素覆盖了前面的元素。多出的那两个数没有被移除掉而已。
那么我们应该如何真正完成移除呢?remove函数会返回一个迭代器,那个迭代器是这个序列的逻辑终点,也即是我代码里的endOfNumbers,它指向倒数第二个5上。
于是我们要利用list的erase函数完成元素移除
numbers.erase(endOfNumbers, numbers.end());
这样我们就完成了我们的工作,稍稍有点曲折……
其实我们可以把这两步放在一起,比如如果我想接着移除所有值为2的元素
numbers.erase(remove(numbers.begin(), numbers.end(), 2), numbers.end());
这样我们就可以一步到位了。
但是这样好么?
不好。
大家会发现,remove函数的原理是复制而不是指针的移动(因为函数操纵的是迭代器,而C++的迭代器没有定义删除操作),这样会带来一个问题:我们使用list是因为它的修改的效率非常高,改变一下指针就可以了。而这里我们复制了元素,如果在vector中,可能还是高效的,因为vector无论如何都要复制,而对于list就不是如此了,会极度降低我们的效率。
那我们怎么办呢?
答案是使用list自己的remove函数
numbers.remove(1);
我们可以这样删除所有值为1的元素。
也即是说,如果要删除list中的元素,我们应该使用list的remove成员函数,而不是remove算法!
相关文章推荐
- IOS学习之——借用别人的应用图片 启动图片
- 单元测试
- HDU2181
- nyist 201 作业题(最长上升子序列和最长下降子序列)
- string 示例程序失败
- android基础学习之一个简单的歌词滚动软件的实现
- Spring和C3P0数据连接池使用
- 软件项目管理(4)
- 【游戏服务端开服 三 】 异步通信的服务端
- 虚拟机VMWare安装RHEL 7.0以及安装配置LAMP环境(Apache+PHP+MariaDB)
- Ubuntu SecureCRT 破解
- POJ 2446
- 史上最全的iOS面试题及答案
- HDU 2461 Rectangles
- Mybatis 控制台输出sql信息
- IOS学习之——使用UIWebView打开其他常见文件
- 算法:选择排序
- qwe
- Controlling Session Behavior in Asp.Net MVC4
- 关于onTouchEvent跟onInterceptEvent的事件处理