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 ...
随机推荐
- HanLP 配置与使用
https://github.com/hankcs/HanLP 下载 hanlp-1.6.0.jar和 hanlp.properties 放在主目录下 修改 hanlp.properties 参考官网 ...
- selenium 定位无标签的元素
转载需注明出处. 如: ::before 伪元素xpath css_selector. id. class_name各种定位失效,可以选择用, .get_attribute('innerHTML')方 ...
- 将js和css文件装入localStorage加速程序执行
原理如下: 一次批量加要加载的文件存入数组,采用Ajax方式异步载入各个文件,然后采用循环方式逐个执行下载下来的Js或者Css文件,如果已经被缓存(localStorage)的则省略下载过程. 由于J ...
- [LeetCode&Python] Problem 350. Intersection of Two Arrays II
Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1,2,2,1 ...
- java实现图片上传功能,并返回图片保存路径
1.前端html <div class="form-group"> <label for="inputPassword3" class ...
- lesson6-图像分割-小象c
显著性检测:1)显著性物体检测-最能引起视觉注意的物体区域2)注视点预测:人类视觉注意机制 视觉注意机制的两种机制:1)自底而上基于数据驱动的注意机制,如颜色.边缘 2)自上而下基于任务驱动的目标的注 ...
- Promise-js中的同步和异步
js中的同步和异步 自从读了研后,走上了学术之路,每天除了看论文就是做实验,最后发现自己还是喜欢开发呀,于是我又重回前端啦~ 隔了这么久没学前端,好像很多东西都忘了不少,而且不得不说前端的技术更新 ...
- MYSQL 常用函数大全
1. 数学函数 greatest(x1,x2,...,xn)返回集合中最大的值 least(x1,x2,...,xn) 返回集合中最小的值 rand()返回0到1内的随机值,可以通过提供一个参数(种子 ...
- canvas 使用 isPointInPath() 判断鼠标位置是否在绘制的元素上
canvas 里绘制的图形不是一个实体 DOM,所以要给每个绘制的图形添加事件操作比给 DOM 添加事件要复杂很多. 所以,我们需要使用一个 canvas 的 isPointInPath(x, y) ...
- LeetCode - Flood Fill
An image is represented by a 2-D array of integers, each integer representing the pixel value of the ...