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;
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • 详解C++ STL vector容器访问元素的几种方式

    学会如何创建并初始化 vector 容器之后,本节继续来学习如何获取(甚至修改)容器中存储的元素. 访问vector容器中单个元素 首先,vector 容器可以向普通数组那样访问存储的元素,甚至对指定下标处的元素进行修改,比如: #include <iostream> #include <vector> using namespace std; int main() { vector<int> values{1,2,3,4,5}; //获取容器中首个元素 cout &l

  • c++ vector模拟实现的全过程

    一.vector是什么? vector是表示可变大小数组的序列容器,它也采用连续存储空间来存储元素,因此可以采用下标对vector的元素进行访问,它的大小是动态改变的,vector使用动态分配数组来存储它的元素: 二.容器特性 1.顺序序列 顺序容器中的元素按照严格的线性顺序排序.可以通过元素在序列中的位置访问对应的元素; 2.动态数组 支持对序列中的任意元素进行快速直接访问,甚至可以通过指针进行该操作.操供了在序列末尾相对快速地添加/删除元素的操作; 3.能够感知内存分配器的 容器使用一个内存

  • C++中vector操作方式详解(多种方式)

    1. vector: 1.1 vector 说明 vector是向量类型,可以容纳许多类型的数据,因此也被称为容器 (可以理解为动态数组,是封装好了的类) 进行vector操作前应添加头文件#include <vector> 1.2 vector初始化: 方式1. //定义具有10个整型元素的向量(尖括号为元素类型名,它可以是任何合法的数据类型),不具有初值,其值不确定 vector<int>a(10); 方式2. //定义具有10个整型元素的向量,且给出的每个元素初值为1 vec

  • c++ vector对象相关总结

    下面随笔讲解c++ vector对象. vector对象 为什么需要vector? 封装任何类型的动态数组,自动创建和删除. 数组下标越界检查. 封装的如ArrayOfPoints也提供了类似功能,但只适用于一种类型的数组. vector对象的定义 vector<元素类型> 数组对象名(数组长度); 例: vector<int> arr(5) 建立大小为5的int数组 vector对象的使用 对数组元素的引用 与普通数组具有相同形式: vector对象名 [ 下标表达式 ] vec

  • c++中vector的使用和模拟实现

    一.接口介绍 1.插入数据 void push_back(const T& x) 在当前vector尾部插入x,如果容量不够扩大二倍. iterator insert(iterator pos, const T& x) 在POS位置插入元素x 2.容量相关 size_t capacity() 返回当前vector的容量(size+剩余容量) size_t size() 返回当前vector的元素个数 void resize(size_t n, const T& val = T())

  • 详解C++ STL vector容量(capacity)和大小(size)的区别

    很多初学者分不清楚 vector 容器的容量(capacity)和大小(size)之间的区别,甚至有人认为它们表达的是一个意思.本节将对 vector 容量和大小各自的含义做一个详细的介绍. vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数:而 vector 容器的大小(用 size 表示),指的是它实际所包含的元素个数. 对于一个 vector 对象来说,通过该模板类提供的 capacity() 成员函数,可以获得当前容器的容量

  • C++ vector扩容解析noexcept应用场景

    c++11提供了关键字noexcept,用来指明某个函数无法--或不打算--抛出异常: void foo() noexcept; // a function specified as will never throw void foo2() noexcept(true); // same as foo void bar(); // a function might throw exception void bar2() noexcept(false); // same as bar 所以我们需要

  • C++ vector类的模拟实现方法

    vector和string虽然底层都是通过顺序表来实现的,但是他们利用顺序表的方式不同,string是指定好了类型,通过使用顺序表来存储并对数据进行操作,而vector是利用了C++中的泛型模板,可以存储任何类型的数据,并且在vector中,并没有什么有效字符和容量大小的说法,底层都是通过迭代器进行操作的,迭代器底层实现也就是指针,所以说,vector是利用指针对任何顺序表进行操作的. vector属性 _start用于指向第一个有效元素 _finish用于指向最后一个有效元素的下一个位置 _e

  • C++ vector容器 find erase的使用操作:查找并删除指定元素

    概念:容器.迭代器.算法 STL包括容器.迭代器和算法: 容器 用于管理一些相关的数据类型.每种容器都有它的优缺点,不同的容器反映出程序设计的不同需求.容器自身可能由数组或链表实现,或者容器中的每个元素都有特殊的关键值. 迭代器 用于遍历一个数据集中的每个元素.这些数据集可能是容器或者容器的子集.迭代器的主要优点是它们为任意类型的容器提供一个小巧并且通用(注意通用很重要)的接口.例如,迭代器接口的一个操作是让它依次遍历数据集的每个元素.这个操作是依赖容器的内总部结构独立完成的.迭代器之所以有效是

  • C++中vector容器使用详细说明

    在c++中,vector是一个十分有用的容器,下面通过本文给大家介绍C++中vector容器使用详细说明,具体介绍如下所示 1. 在C++中的详细说明 vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库. vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据. 2. 使用vector,必须在你的头文件中包含下面的代码: #include vec

  • 关于STL中vector容器的一些总结

    1.vector的简单介绍 vector作为STL提供的标准容器之一,是经常要使用的,有很重要的地位,并且使用起来也是灰常方便.vector又被称为向量,vector可以形象的描述为长度可以动态改变的数组,功能和数组较为相似.实际上更专业的描述为:vector是一个多功能的,能够操作多种数据结构和算法的模板类和函数库,vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据.(注:STL的容器从实现的

  • C++中的vector容器对象学习笔记

    C++中数组很坑,有没有类似Python中list的数据类型呢?类似的就是vector! vector 是同一种类型的对象的集合 ,每个对象都有一个对应的整数索引值.和 string 对象一样,标准库将负责管理与存储元素相关的内存. 我们把 vector 称为容器,是因为它可以包含其他对象 . 一个容器中的所有对象都必须是同一种类型的 . vector对象的定义和初始化 同样的,使用前,导入头文件#include <vector> 可以使用using声明:using std::vector;

  • C++入门笔记之std::vector容器详解

    目录 前言 1. vector的构造函数原型: 2. vector的赋值函数原型: 3. vector的容量和大小函数原型: 4. vector的插入和删除函数原型: 5. vector的存取操作函数原型: 6. vector的呼唤容器函数原型: 总结 前言 vector实质是C++的一个类,与数组很相似,但是vector的优势是可以动态扩展,不需要考虑其内存大小. 定义: 向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container).跟任意其它类型容器一样,它

  • C++之vector容器的的声明初始化和增删改查

    C++vector容器 C++中有两种类型的容器:顺序容器和关联容器. 顺序容器主要有vector.list.deque等.其中vector表示一段连续的内存,基于数组实现,list表示非连续的内存,基于链表实现,deque与vector类似,但是对首元素提供插入和删除的双向支持. 关联容器主要有map和set.map是key-value形式,set是单值.map和set只能存放唯一的key,multimap和multiset可以存放多个相同的key. 容器类自动申请和释放内存,因此无需new和

  • C++示例讲解vector容器

    目录 vector基本概念 创建 vector 的各种方法 vector容器的构造 vector赋值操作 vector容量和大小 vector容器插入和删除 vector数据存取 vector互换容器 vector基本概念 功能: vector数据结构和数组非常相似,也称为单端数组 vector与普通数组区别: 不同之处在于数组是静态空间,而vector可以动态扩展 动态扩展: 并不是在原空间之后继续接新空间,而是找更大的内存空间,然后将元数据拷贝新空间,释放原空间 创建 vector 的各种方

  • C++中vector容器的用法

    在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结. 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<int> vec; (3)尾部插入数字:vec.push_back(a); (4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的. (5)使用迭代器访问元素. vector<int>::iterator it; for(it=vec.begi

  • 详解C++中的vector容器及用迭代器访问vector的方法

    vector vector是相同类型对象的集合.集合中的每个对象有个对应的索引.vector常被称为容器(container). 为了使用vector,需要: #include <vector> using std::vector; vector是一个类模版(class template).C++有函数模版和类模版.模版本身不是函数或类,必须通过指定 类型让编译器去实例化(instantiation)它.比如vector<int> ivec. vector是模版,不是类型.从vec

  • C++中vector容器的常用操作方法实例总结

    1 获得容器最后一个元素  ------ 使用 back或rbegin 取得 // back.rbegin 有常量和引用两种形式 std::vector<int> myVector; myVector.back()=3; std::vector<int>::reverse_iterator tailIter; tailIter=myVector.rbegin(); *tailIter=3 2 删除某元素 需要删除某位置的元素,应使用iterator遍历, 不应使用at(i) 方式遍

随机推荐