平时一般使用都是vector,但是涉及到频繁删除元素的时候,就会用到list,因为vector每次删除后,删除元素后面的每个元素的迭代器都要重新分配,导致效率低下,而且十分麻烦。但是list使用erase和remove删除元素时,也会存在很多坑。
一下是之前一篇博文中的vector和list删除元素的时间效率比较:
每个测试数据下面的第一行,第二行分别是vector和list
10:
Used time is = 16ms
Used time is = 12ms
100:
Used time is = 526ms
Used time is = 89ms
1000:
Used time is = 28242ms
Used time is = 1334ms
10000:
Used time is = 2532717ms
Used time is = 13984ms
*/
————————————————
版权声明:本文为CSDN博主「繁星蓝雨」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33375598/article/details/104778027
1 erase(搭配迭代器)
list<int> List;
List.push_back(1);
List.push_back(1);
List.push_back(3);
List.push_back(1);
List.push_back(1);
List.push_back(5);
List.push_back(1);
List.push_back(1);
for (list<int>::iterator i = List.begin(); i != List.end(); ++i) {
if(*i == 1){
List.erase(i);
}
}
for (list<int>::const_iterator i = List.begin(); i != List.end(); ++i) {
if(i != List.begin()) cout <<" ";
cout << *i;
}
上面的代码,大家可能以为会输出1 3 1 5 1
因为大家会认为删除list的一个迭代器后,会让迭代器指向下一个,然后for循环的条件i++,迭代器再往后移动一次,连续的1就会被跳过。 (不成立)
但是实际上会输出:
但是实际上,list使用erase删除一个迭代器后,会保留原始索引,仍能输出删除迭代器所指的值,使用erase后返回的是下一个迭代器。
测试程序:
list<int> List;
List.push_back(1);
// List.push_back(1);
List.push_back(3);
List.push_back(1);
List.push_back(1);
List.push_back(5);
List.push_back(1);
List.push_back(1);
for (list<int>::iterator i = List.begin(); i != List.end(); ++i) {
if(*i == 1){
list<int>::iterator temp = List.erase(i);
cout << "temp:" << *temp <<" ";
cout << "i:"<<*i <<" ";
}
}
输出:
结论是:使用erase后,当前的迭代器不会自动+1。
2 remove(搭配值)
一开始我以为remove(value)只是删除第一个查询到的value,但是实际上它会删除容器中所有value,因此不需要使用for循环,即可删除容器中所有等于value的值。
但是使用remove(value)后,会立即使所有值为value的迭代器全部失效,结果就是,当你再使用失效迭代器时,程序就会报错。
list<int> List;
List.push_back(1);
// List.push_back(1);
List.push_back(3);
List.push_back(1);
List.push_back(1);
List.push_back(5);
List.push_back(1);
List.push_back(1);
for (list<int>::iterator i = List.begin(); i != List.end(); ++i) {
cout << "test:" << *i;
List.remove(1);
}
编译不报错,但是逐步调试就会发现错误:
原因就是使用了失效的迭代器。
3 在while来使用erase
举例(源自自己的一篇博文:https://blog.csdn.net/qq_33375598/article/details/104778027):
list<int> List, fail;
list<int>::iterator iter = List.begin();
while(iter != List.end()){
if(fgrade(*iter)){
fail.push_back(*iter);
iter = List.erase(iter);
}else{
++iter;
}
}