删除元素

从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. mxnet 动手学深度学习

    http://zh.gluon.ai/chapter_crashcourse/introduction.html 强化学习(Reinforcement Learning) 如果你真的有兴趣用机器学习开 ...

  2. strcmp用法

    strcmp() 用来比较字符串(区分大小写),其原型为:    int strcmp(const char *s1, const char *s2); [参数]s1, s2 为需要比较的两个字符串. ...

  3. [LeetCode&Python] Problem 783. Minimum Distance Between BST Nodes

    Given a Binary Search Tree (BST) with the root node root, return the minimum difference between the ...

  4. (1)MySQL(入门操作安装\基本指令)

    什么是MySQL MySQL本质上就是用来管理数据的---用来做增.删.改.查 使用MySQL后管理数据就相对简单方便 数据库软件的种类: 1.什么是关系型数据库(关系型数据库特点就是对数据格式可以有 ...

  5. SpringMVC整合Thymeleaf

    Thymeleaf的介绍 进行JavaWeb开发时主要用到的是JSP,传统的JSP需要在页面中加入大量的JSTL标签,这些标签只能运行在服务器中,前端开发人员维护这些页面比较困难,页面加载速度也比较慢 ...

  6. 《DSP using MATLAB》Problem 6.8

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...

  7. hdu1542 Atlantis 线段树--扫描线求面积并

    There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...

  8. MySQL--时间戳与时区问题

    对于使用 timestamp 的场景,MySQL 在访问 timestamp 字段时会做时区转换,当 time_zone 设置为 system 时,MySQL 访问每一行的 timestamp 字段时 ...

  9. 使用OpenCV进行人脸识别

    不断维护的地址:http://plzcoding.com/face-recognition-with-opencv/ 怎样使用OpenCV进行人脸识别 本文大部分来自OpenCV官网上的Face Re ...

  10. 用IBM MQ中间件开发碰到的MQRC_NOT_AUTHORIZED(2035)问题

    我在一台工作站上面部署了MQ服务器,在MQ服务器中我建立了队列管理器MQ_TEST,在该队列管理器中我建立了一个本地队列MQ_Q以及一个服务器连接通道MQ_C,MQ_C中的MCA用户标识默认为空.同时 ...