STL进阶--删除元素
删除元素
从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进阶--删除元素的更多相关文章
- STL容器删除元素的陷阱
今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector< ...
- c++之STL容器删除元素
1.删除容器中特定值的元素 如果是容器vector,string,,deque,使用erase-remove 例如:erase-remove 注:因为container没有remove,contain ...
- STL中用erase()方法遍历删除元素 .xml
pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9; ...
- STL中用erase()方法遍历删除元素
STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.set.map).在使用erase方法来删除元素时 ...
- STL 中 使用迭代器删除元素的问题
在vector中删除,大家都知道,直接erase的话,这种写法很有问题.因为erase(iter)之后iter指针就变成野指针了,此时继续iter++就会出问题. for(auto iter = v. ...
- js进阶 9-11 select选项框如何动态添加和删除元素
js进阶 9-11 select选项框如何动态添加和删除元素 一.总结 一句话总结: 二.js进阶 9-11 select选项框如何动态添加和删除元素 1.案例说明 2.相关知识 Select 下拉列 ...
- 怎么删除STL容器的元素
在STL容器有顺序容器和关联容器两种. 顺序容器删除元素的方法有两种: 1.c.erase(p) 从c中删除迭代器p指定的元素.p必须指向c中一个真实元素,不能等于c.end().返回一个指向p之后元 ...
- STL——遍历 删除 set 元素
==================================声明================================== 本文版权归作者所有. 本文原创,转载必须在正文中显要地注明 ...
- STL容器迭代过程中删除元素技巧(转)
1.连续内存序列容器(vector,string,deque) 序列容器的erase方法返回值是指向紧接在被删除元素之后的元素的有效迭代器,可以根据这个返回值来安全删除元素. vector<in ...
随机推荐
- 九度OJ1153-括号匹配-栈的应用
题目1153:括号匹配问题 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:9697 解决:4213 题目描述: 在某个字符串(长度不超过100)中有左括号.右括号和大小写字母:规定(与常见 ...
- 2018.10.25 CCSP马拉松摸铜归来
24号体测跑50+1000米. 50米抢跑被罚重跑???然后老年人就只能吊着一口仙气跑第二次50米.然后跑1000米,然后再到宿舍收拾行李赶往地铁站,然后再冲到火车站...(卒) 宾馆,三人挤入二人房 ...
- Python知识点整理,基础3 - 字典操作
- Js 分别取一个数的百位,十位,个位
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...
- MySQL5.6在线DDL不锁表(在线添加字段)
解答你也看一下MySQL5.6在线DDL不锁表,现在我有一张1亿的表,需要增加一个字段,假如我让你去增加这个字段,你应该注意什么,具体怎么操作? 操作如下:1.注意磁盘空间(临时表目录 参数 tmpd ...
- c的动态内存管理
在linux系统下使用malloc提示警告,解决方法,加入头文件<stdlib.h> 首先来个基本的例子 int *p=(int *)malloc(sizeof(int));(当mallo ...
- sqler sql 转rest api 源码解析(四)macro 的执行
macro 说明 macro 是sqler 的核心,当前的处理流程为授权处理,数据校验,依赖执行(include),聚合处理,数据转换 处理,sql 执行以及sql 参数绑定 授权处理 这个是通过go ...
- Benthos metrcis 说明
Benthos 按照input, pipeline ,buffer,conditions,ouput 这个几个大类,为我们提供了 方便的分析metrics,支持json 格式同时可以暴露为 stats ...
- 初等数论及其应用 (第6版) (Kenneth H.Rosen 著)
第1章 整数 1.1 数和序列 1.2 和与积 1.3 数学归纳法 1.4 斐波那契数 1.5 整除性 第2章 整数的表示法和运算 2.1 整数的表示法 2.2 整数的计算机运算 2.3 整数运算的复 ...
- Python time & datetime模块
time 模块 时间分为三种格式: 时间戳:表示1970年1月1日之后的秒 结构化时间:元组包含了:年.日.星期等... 格式化字符串:格式可以自定义 时间戳: import time time_st ...