C++ vector容器 find erase的使用操作:查找并删除指定元素
概念:容器、迭代器、算法
STL包括容器、迭代器和算法:
容器
用于管理一些相关的数据类型。每种容器都有它的优缺点,不同的容器反映出程序设计的不同需求。容器自身可能由数组或链表实现,或者容器中的每个元素都有特殊的关键值。
迭代器
用于遍历一个数据集中的每个元素。这些数据集可能是容器或者容器的子集。迭代器的主要优点是它们为任意类型的容器提供一个小巧并且通用(注意通用很重要)的接口。例如,迭代器接口的一个操作是让它依次遍历数据集的每个元素。这个操作是依赖容器的内总部结构独立完成的。迭代器之所以有效是因为容器类提供它自己的迭代器类型来做“正确的事”,容本身的迭代器了解容器的内部结构。
迭代器的接口几乎相当于普通的指针。让一个迭代器递增只需调用++操作符。使用*操作符可以得到迭代器引用的数据值。因而迭代器可以被任为是一种智能指针。
算法
被用于处理数据集中的元素。例如它们可以搜索、排序、修改数据或者其他目的。算法使用迭代器,因此,一个算法只需被编写一次就可以用于任意的容器,因为迭代器的接口对所有类型的容器是通用的。这就是find()的位置
为了给算法更多的扩展性,需要提供一些被算法调用的附属函数。可以使用通用算法去适应非常特别和复杂的需求。你可以提供自己的搜索标准或者特殊的操作去绑定元素。
STL的概念是将数据和操作独立开来。数据由容器类管理,而操作是由可配置的算法定义。迭代器则是这两个元素之间的线索。它允许任何算法和容器的交互。
在某种意义上,STL的概念有勃于面向对象编程的初衷:STL将数据和算法分离而非绑定它们。然而,这样做的理由非常重要:原则上,你可以将任何容器同任何算法绑定,得到的结果是STL是非常可扩展的。
STL的一个标准是它支持任意数据类型。“标准模板库”意味着,所有部分是适应任意类型的模板。STL是通用编程的例子。容器和算法对任意类型和类都是通用的。
STL甚至提供更多的通用组件。使用 适配器 和函数体,你可以为特定需要补充、限制和配置算法和接口。
注意find不属于vector的成员,而存在于算法中,应加上头文件#include <algorithm>
C++ vector 删除符合条件的元素
包含头文件:
#include <iostream> #include <vector> #include <algorithm>//注意要包含该头文件
C++ vector中实际删除元素使用的是容器vector中std::vector::erase()方法。
C++ 中std::remove()并不删除元素,因为容器的size()没有变化,只是元素的替换。
1.erase( ) 删除元素
函数原型:
iterator erase (iterator position);//删除指定元素 iterator erase (iterator first, iterator last);//删除指定范围内的元素
返回值:指向删除元素(或范围)的下一个元素。
(An iterator pointing to the new location of the element that followed the last element erased by the function call. This is the container end if the operation erased the last element in the sequence.)
对于c++里面的容器, 我们可以使用iterator进行方便的遍历. 但是当我们通过iterator对vector/map等进行修改时, 我们就要小心了。
cplusplus的reference里对 std::vector::erase 的描述是:
Iterators, pointers and references pointing to position (or first) and beyond are invalidated, with all iterators, pointers and references to elements before position (or first) are guaranteed to keep referring to the same elements they were referring to before the call.
由上可知,原有iter指针在删除元素后会失效,之后的行为都变得不可预知.。
对于vector, erase会返回下一个iterator, 因此我们可以使用如下的方法:
#include <iostream> #include <vector> using namespace std; int main() { vector<int> a = { 12, 23, 34, 45, 56, 67, 78, 89 }; auto iter = a.begin(); while (iter != a.end()) { if (*iter > 30) { iter = a.erase(iter);//用iter接收返回值 } else //不要忘记这一段 { ++iter; } } for (const auto &element : a) { cout << element << endl; } return 0; }
实现代码
例1. 用while循环查找并删除一个元素
#include <vector> using namespace std; void main(void) { vector<int> array; array.push_back(1); array.push_back(2); array.push_back(3); array.push_back(4); array.push_back(5); vector<int>::iterator itr = array.begin(); while (itr != array.end()) { if (*itr == 3) { itr = array.erase(itr);//删除元素,返回值指向已删除元素的下一个位置 } else { ++itr; } } }
例2. 用for循环遍历删除所有元素
#include <vector> #include <iostream> using namespace std; int main() { vector<int> test_vec; for (int i = 0; i<100;i++) { test_vec.push_back(i); } for(vector<int>::iterator it = test_vec.begin(); it != test_vec.end(); ) { cout<<*(it)<<endl; it = test_vec.erase(it); } return 0; }
例3. 删除重复元素
若要求按照数据原来的顺序,参照本文最后的代码
若不要求按照数据原来的顺序,可用:
sort(v.begin(),v.end()); //unique只能比较相邻元素是否重复 v.erase(unique(v.begin(), v.end()), v.end()); //unique将重复的元素移到末尾,返回末尾中第一个重复值的地址
2.find( ) 查找元素
官方文档给出的定义:
find (STL)
在范围中找到具有指定值的元素的第一个匹配项位置。
用于确定要在范围中搜索的指定值第一次出现的位置的输入迭代器。 如果找不到具有等效值的元素,则返回 last。
template<class InputIterator, class T> InputIterator find(InputIterator first, InputIterator last, const T& val);
first
用于确定要在范围中搜索其指定值的第一个元素的位置的输入迭代器。
last
用于确定要在范围中搜索其指定值的最后一个元素之后下一个元素的位置的输入迭代器。
val
要搜索的值。
find() 函数:在容器内查找指定的元素,这个元素必须是基本数据类型的。
语法:find(arr.begin(), arr.end(), 50);第一个参数是array的起始地址,第二个参数是array的结束地址,第三个参数是需要查找的值。
如果想从指定位置开始查找,可以这样写:find(c.begin()+i+1, c.end(), c[i]);
其中i为自定义的位移量,结合for循环可以实现从当前位置开始查找
查找成功:返回一个指向指定元素的迭代器
查找失败:返回end迭代器
STL库中,find( )源码如下:
template <class InputIterator, class T> InputIterator find(InputIterator first, InputIterator last, const T& value) { while (first != last && *first != value) { ++first; } ++first; return first; }
用find查找并删除一个元素
#include<iostream> #include<algorithm> #include<vector> using namespace std; vector<int> arr(100);//整型的array数组 int main() { arr[20] = 50;//其余都是默认值0 vector<int>::iterator s = find(arr.begin(), arr.end(), 50);//第一个参数是array的起始地址,第二个参数是array的结束地址,第三个参数是需要查找的值 if (s != arr.end())//如果找到,就输出这个元素 { cout << *s << endl; } else//如果没找到 { cout << "not find!" << endl; } system("pause"); return 0; }
另外还有一个函数: find_if函数
find_if函数,带条件的查找元素。
容器元素类型是类的时候,不能使用find函数,只能通过find_if函数来实现。
find_if函数依次的遍历容器的元素,返回第一个使函数为true的元素的迭代器;如果查找失败则返回end迭代器。
3.remove()
std::vector没有直接删除特定值元素的成员方法。所以必须使用remove算法:
std::vector <Elem> coll; //remove all elements with value val coll.erase(remove(coll.begin(), coll.end(), val), coll.end());
remove()返回的是删除后的尾部迭代器,必须调用erase()显式地删除其后的元素。
如果仅删除第一个特定值元素:
std::vector <Elem> coll; //remove first element with value val std::vector<Elem>::iterator pos; pos = find(coll.begin(), coll.end(), val); if (pos != coll.end()) { coll.erase(pos); }
4.代码实例(一道牛客网练习题)
内容:
输入两行字符c[ ], b[ ];
该程序把c[ ]中与b[ ]重复的元素全部删除
并且把c[ ]本身内部重复的元素也删除(大小写被一律转化为大写)
最后输出剩余的不重复的元素
#include<iostream> #include<string> #include<map> #include<vector> #include<algorithm> using namespace std; int main() { vector <char> c; vector <char> d; char keyBoard; //输入c数组,用回车结束 while (keyBoard = getchar()) { if (keyBoard == '\n')break; c.push_back(keyBoard); } //输入d数组,用回车结束 while (keyBoard = getchar()) { if (keyBoard == '\n')break; d.push_back(keyBoard); } //c-d:c,d数组对比,删除c数组中与d数组相同的元素 vector<char>::iterator iter = c.begin(); int i; for (i = 0; i < d.size(); i++) { iter = find(c.begin(), c.end(), d[i]); if (iter != c.end()) { c.erase(iter); } } //把c数组中剩余的小写字母转换为大写,其余字符不变 for (i = 0; i < c.size(); i++) { if (c[i] >= 'a'&&c[i] <= 'z') { c[i] -= 32; } } //删除c数组中的重复元素 for (i = 0; i < c.size(); i++) { iter = find(++(find(c.begin(), c.end(), c[i])), c.end(), c[i]);//巧妙用++,从第一个想要查找的元素开始查找,删除后面的,保留第一个 if (iter != c.end()) { c.erase(iter); i--; } } //输出c数组中的所有元素 for (i = 0; i < c.size(); i++) { cout << c[i]; } return 0; }
补充:C++ STL vector容器元素的查找和搜索 find() find_if()函数的使用
看代码吧~
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; void print(const int& temp){ cout<<temp<<endl; } int main() { const int ARRAY_SIZE=8; int IntArray[ARRAY_SIZE]={1,2,3,4,5,6,7}; vector<int> myvt; vector<int>::iterator location_index; for(int i=0;i<8;++i){ myvt.push_back(IntArray[i]); } for_each(myvt.begin(),myvt.end(),print); location_index=find(myvt.begin(),myvt.end(),2); //find函数 cout<<"数字2的下标是:"<<(location_index-myvt.begin())<<endl; location_index=find_if(myvt.begin(),myvt.end(),bind2nd(greater<int>(),5)); cout<<"第一个大于5的数字的下标是:"<<(location_index-myvt.begin())<<endl; return 0; }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。