删除元素

从vector或deque删除元素

  vector<int> vec = {1, 4, 1, 1, 1, 12, 18, 16}; // 删除所有的1
for (vector<int>::iterator itr = vec.begin(); itr != vec.end(); ++itr) {
if ( *itr == 1 ) {
vec.erase(itr); //你或许会想到使用erase成员函数
}
} // 的确,是可以达到目的 vec: { 4, 12, 18, 16}
// 但是复杂度是: O(n*m),每删除一个元素,后面的往前移动 // 如果使用算法remove
remove(vec.begin(), vec.end(), 1); // 复杂度 O(n)
// vec: {4, 12, 18, 16, ?, ?, ?, ?} vector<int>::iterator newEnd = remove(vec.begin(), vec.end(), 1); // 将不删除的元素移到前面,O(n)
vec.erase(newEnd, vec.end()); //删除最后无用的元素 // 算法remove_if()和unique()也是类似 // 此时vec仍然占了8个int空间: vec.capacity() == 8
vec.shrink_to_fit(); // C++ 11
// 现在vec.capacity() == 4 // For C++ 03:
vector<int>(vec).swap(vec); // 相同效果,释放空的内存

从List删除

  list<int> mylist = {1, 4, 1, 1, 1, 12, 18, 16};

  list<int>::iterator newEnd = remove(mylist.begin(), mylist.end(), 1);  // 使用算法remove,O(n)
mylist.erase(newEnd, mylist.end()); mylist.remove(1); // 成员函数更快,直接操作指针,从链上删除

从关联容器或无序容器中删除

  multiset<int> myset = {1, 4, 1, 1, 1, 12, 18, 16};

  multiset<int>::iterator newEnd = remove(myset.begin(), myset.end(), 1);  // O(n)
myset.erase(newEnd, myset.end()); myset.erase(1); // O(log(n)) or O(1)

结论

  • vector或者deque: 算法remove() + erase()
  • list:成员函数remove()
  • 关联容器或者无序容器:成员函数erase()

删除元素之后

// 看个关联容器的例子,此程序会发生什么
multiset<int> s = {1, 4, 1, 1, 1, 12, 18, 16};; multiset<int>::iterator itr;
for (itr=s.begin(); itr!=s.end(); itr++) {
if (*itr == 1) {
s.erase(itr);
cout << "Erase one item of " << *itr << endl;
}
} // 删除第一个元素成功,后面未定义的行为

解决方法:

multiset<int>::iterator itr;
for (itr=s.begin(); itr!=s.end(); ) {
if (*itr == 1) {
cout << "Erase one item of " << *itr << endl;
s.erase(itr++); //在删除之前,迭代器已经指向下一个
} else {
itr++;
}
}

对于序列容器

vector<int> v = {1, 4, 1, 1, 1, 12, 18, 16};
vector<int>::iterator itr2;
for (itr2=v.begin(); itr2!=v.end(); ) {
if (*itr2 == 1) {
cout << "Erase one item of " << *itr2 << endl;
v.erase(itr2++); //这样仍然不安全,删除的元素后面的所有迭代器都失效
} else {
itr2++;
}
}

解决方法:

for (itr2=v.begin(); itr2!=v.end(); ) {
if (*itr2 == 1) {
cout << "Erase one item of " << *itr2 << endl;
itr2 = v.erase(itr2);
} else {
itr2++;
}
} // 1 序列容器和无序容器的erase返回指向删除元素下一个元素的迭代器
// 2. 关联容器的erase不返回东西

总结

  • 序列容器和无序容器使用:it = c.erase(it);
  • 关联容器:c.erase(it++);

使用算法

vector<int> c = {1, 4, 1, 1, 1, 12, 18, 16};

//普通函数
bool equalOne(int e) {
if (e == 1) {
cout << e << " will be removed" << endl;
return true;
}
return false;
}
auto itr = remove_if(c.begin(), c.end(), equalOne);
c.erase(itr, c.end()); //使用bind():
bool equalOne(int e, int pattern) {
if (e == pattern) {
cout << e << " will be removed" << endl;
return true;
}
return false;
}
remove_if(v.begin(), v.end(), bind(equalOne, placeholders::_1, 1)); // Lambda函数:
auto itr = remove_if(v.begin(), v.end(),
[](int e){
if(e == 1) {
cout << e << " will be removed" <<endl; return true;
}
}
);

STL进阶--删除元素的更多相关文章

  1. STL容器删除元素的陷阱

    今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector< ...

  2. c++之STL容器删除元素

    1.删除容器中特定值的元素 如果是容器vector,string,,deque,使用erase-remove 例如:erase-remove 注:因为container没有remove,contain ...

  3. STL中用erase()方法遍历删除元素 .xml

    pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9; ...

  4. STL中用erase()方法遍历删除元素

    STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.set.map).在使用erase方法来删除元素时 ...

  5. STL 中 使用迭代器删除元素的问题

    在vector中删除,大家都知道,直接erase的话,这种写法很有问题.因为erase(iter)之后iter指针就变成野指针了,此时继续iter++就会出问题. for(auto iter = v. ...

  6. js进阶 9-11 select选项框如何动态添加和删除元素

    js进阶 9-11 select选项框如何动态添加和删除元素 一.总结 一句话总结: 二.js进阶 9-11 select选项框如何动态添加和删除元素 1.案例说明 2.相关知识 Select 下拉列 ...

  7. 怎么删除STL容器的元素

    在STL容器有顺序容器和关联容器两种. 顺序容器删除元素的方法有两种: 1.c.erase(p) 从c中删除迭代器p指定的元素.p必须指向c中一个真实元素,不能等于c.end().返回一个指向p之后元 ...

  8. STL——遍历 删除 set 元素

    ==================================声明================================== 本文版权归作者所有. 本文原创,转载必须在正文中显要地注明 ...

  9. STL容器迭代过程中删除元素技巧(转)

    1.连续内存序列容器(vector,string,deque) 序列容器的erase方法返回值是指向紧接在被删除元素之后的元素的有效迭代器,可以根据这个返回值来安全删除元素. vector<in ...

随机推荐

  1. Django中Ajax处理

    1.大部分和Flask中相同. 2.Django处理JSON,主要是对于查询结果集处理. 使用Django提供的序列化的类来完成QuerySet到JSON字符串的转换 from django.core ...

  2. java-代码块-局部代码块、构造代码块、静态代码块

    1.代码块概述: 在Java中,使用{ }括起来的代码被称为代码块. 2.代码块分类: 根据其位置和声明的不同,可以分为局部代码块,构造代码块.静态代码块和同步代码块(多线程). 3.常见代码块的应用 ...

  3. 一次scrapy失败的提示信息:由于连接方在一段时间后没有正确答复或连接的主机没有反 应,连接尝试失败

    2017-10-31 19:09:26 [scrapy.extensions.logstats] INFO: Crawled 8096 pages (at 67 pages/min), scraped ...

  4. 10 HashMap,Map.Entry,LinkedHashMap,TreeMap,Hashtable,Collections类

    Map集合的功能概述 添加功能 * V put(K key,V value):添加元素.            * 如果键是第一次存储,就直接存储元素,返回null            * 如果键不 ...

  5. Tomcat建立多个应用(Web Server),多个主机,多个站点的方法

    https://blog.csdn.net/chungle2011/article/details/52317433 http://piperzero.iteye.com/blog/1475773 转 ...

  6. AangularJS过滤器详解

    (参考angular权威指南) 过滤器:   用来格式化需要展示给用户的数据: 使用过滤器的方式: (1)$scope.name=$filter("lowercase").(&qu ...

  7. ios-根据单元格里的控件tag值,在方法外获得对应的section与row的值

    在cell的代理方法里:cellForRowAtIndexPath btn.tag = indexPath.section *100 + indexPath.row; [cell.exitPerson ...

  8. 【mybatis源码学习】利用maven插件自动生成mybatis代码

    [一]在要生成代码的项目模块的pom.xml文件中添加maven插件 <!--mybatis代码生成器--> <plugin> <groupId>org.mybat ...

  9. JS中map和foreach的区别以及some和every的用法

    一.原生JS forEach()和map()遍历 共同点: 1.都是循环遍历数组中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前 ...

  10. 企业库实现AOP的几种方法

    1.创建新对象时,分继承基类和继承接口 TargetClass theTarget = PolicyInjection.Create<TargetClass>(parameter1, pa ...