问题处理记录

std::vector查找指定元素C++

https://blog.csdn.net/qq_43799400/article/details/122699509
https://blog.csdn.net/weixin_37120663/article/details/120696085


if (std::find(vector.begin(), vector.end(), item) != vector.end())
{
    //查到指定元素时的操作
}
else
{
    //未查到指定元素时的操作
}

概念

vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。

vector每次扩容为原来的两倍,对小对象来说执行效率高,但如果遇到大对象,执行效率就低了。

优点
  1. 不指定一块内存大小的数组的连续存储,即可以像数组一样操作,但可以对此数组进行动态操作。通常体现在push_back() pop_back()
  2. 随机访问方便,即支持[ ]操作符和vector.at()
  3. 节省空间。
缺点
  1. 在内部进行插入删除操作效率低。
  2. 只能在vector的最后进行push和pop,不能在vector的头进行push和pop。
  3. 当动态添加的数据超过vector默认分配的大小时要进行整体的重新分配、拷贝与释放。
使用

为了可以使用vector,必须在你的头文件中包含下面的代码:

#include <vector>

vector属于std命名域的,因此需要通过命名限定,如下完成你的代码:

using std::vector;//不建议使用using namespace std;直接引入std命名域

vector<int> vInts;
//或者连在一起,使用全名:
std::vector<int> vInts;

注意:
对最后元素操作最快(在后面添加删除最快 ), 此时一般不需要移动内存,只有保留内存不够时才需要
对中间和开始处进行添加删除元素操作需要移动内存,如果你的元素是结构或是类,那么移动的同时还会进行构造和析构操作,所以性能不高 (最好将结构或类的指针放入vector中,而不是结构或类本身,这样可以避免移动时的构造与析构)。


vector声明和初始化

vector 型变量的声明以及初始化的形式也有许多, 常用的有以下几种形式:

std::vector<ElemType> c;		//创建一个空的vector
std::vector<ElemType> c1(c2); 	//创建一个vector c1,并用c2去初始化c1
std::vector<ElemType> c(n) ; 	//创建一个含有n个ElemType类型数据的vector;
std::vector<ElemType> c(n,elem); //创建一个含有n个ElemType类型数据的vector,并全部初始化为elem;
//如:
std::vector<int> a ;            //声明一个int型向量a
std::vector<int> a(10) ;        //声明一个初始大小为10的向量
std::vector<int> a(10, 1) ;     //声明一个初始大小为10且初始值都为1的向量
std::vector<int> b(a) ;         //声明并用向量a初始化向量b
std::vector<int> b(a.begin(), a.begin()+3) ; //将a向量中从第0个到第2个(共3个)作为向量b的初始值

ElemType可以为基本的内置类型char,int,double,也可以为结构体/C++对象/string等。

除此之外, 还可以直接使用数组来初始化向量:

int n[] = {1, 2, 3, 4, 5};
std::vector<int> a(n, n+5) ;              //将数组n的前5个元素作为向量a的初值
std::vector<int> a(&n[1], &n[4]) ;        //将n[1] - n[4]范围内的元素作为向量a的初值

vector的基本操作

元素访问

std::vector<int> c;	
c.at(index);		//返回指定index位置处的元素,同时进行越界检查
operator[index]		//返回指定index位置处的元素,有越界风险
c.front();			//返回容器第一个元素
c.back();			//返回容器最后一个元素
c.date();			//返回指向内存中数组第一个元素的指针

迭代器

std::vector<int> c;	
c.begin();			//返回当前vector容器中起始元素的迭代器
c.end();			//返回指向容器最后一个数据单元的指针+1
c.rbegin();			//将vector反转后的开始指针返回(其实就是原来的end-1)
c.rend();			//将vector反转后的结束指针返回(其实就是原来的begin-1)
其他还有:cbegin,cend,crbegin,crend;
//应用
std::vector<int>::iterator it;
for (it = vec.begin(); it != vec.end(); it++) 
	cout << *it << endl;
//或者
for (size_t i = 0; i < vec.size(); i++) {
    cout << vec.at(i) << endl;
}

容量

c.empty();		//判断容器是否为空,若为空返回true,否则返回false
c.size();		//返回当前容器中实际存放元素的个数(比empty速度慢)
c.max_size();	//返回可容纳的最大元素数
c.reserve(num);	//改变当前vecotr所分配空间的大小,设置容器预留空间,但并不真正创建元素对象
c.capacity();	//当前vector分配的大小,linux下c.size()达到容器最大个数时,容器增长为原来的一倍1,2,4,8,16,32,64
c.shrink_to_fit()//通过释放未使用的内存减少内存的使用(C++11)

修改器

c.clear();			//清空当前的vector
c.push_back(elem);	//将元素添加到容器末尾 
c.pop_back();		//移除最后一个末尾元素
c.insert(); 		//插入元素,有多种使用方式
c.erase(); 			//移除元素,有多种使用方式
c.resize(num,defult);//改变容器中可存储元素的个数,并创建对象(default可省略)
c1.swap(c2);		//交换两个容器中的数据
示例:
c.insert(p,elem);	//在指针p指向的位置插入数据elem,返回指向elem位置的指针       
c.insert(p,n,elem);	//在位置p插入n个elem数据,无返回值
c.insert(p,begin,end);//在位置p插入在区间[begin,end)的数据,无返回值
c.erase(begin,end)    	删除begin,end区间的数据,返回指向下一个数据位置的指针(迭代器)

二维向量

与数组相同, 向量也可以增加维数, 例如声明一个m*n大小的二维向量方式可以像如下形式:

vector< vector<int> > b(10, vector<int>(5));        //创建一个10*5的int型二维向量

vector的begin() end() 和 front() back()的区别

https://blog.csdn.net/duan19920101/article/details/51679517/
https://www.cnblogs.com/xiaoyoucai/p/8283548.html

示例

示例一:

#include <iostream>
#include <vector>

using std::cout;
using std::endl;

int main()
{
	std::vector<int> v_queue;

	int a = 5, b = 8, result = 0;

	//在末尾添加元素
	v_queue.push_back( a );
	v_queue.push_back( b );

	//正向迭代器遍历
	for (std::vector<int>::iterator it = v_queue.begin(); it != v_queue.end(); ++it)
	{
		cout << *it << endl;
	}

	if(!v_queue.empty())//或 if(v_queue.size() > 0)
	{
		//获取第一个元素
		result = v_queue.front();
		cout << "result:" << result << endl;

		//移除首个元素
		v_queue.erase(v_queue.begin());
	}

	//反向迭代器遍历
	for (std::vector<int>::reverse_iterator it = v_queue.rbegin(); it != v_queue.rend(); ++it)
	{
		cout << *it << endl;
	}

	//非迭代器遍历
	for(int i = 0; i < v_queue.size(); i++ )//v.size() 表示vector存入元素的个数
 	{
    	cout << v_queue[ i ]; //把每个元素显示出来
 	}
 	return 0;
}

注意事项:

  1. 多线程操作时,需要添加线程锁对数据进行保护;
  2. 但凡使用了迭代器的循环体,都不要向迭代器所属的容器添加元素;

应用场景

参考资料:
https://www.cnblogs.com/zhonghuasong/p/5975979.html
https://www.cnblogs.com/skyfsm/p/6934246.html

C++中Vector.erase()删除某一元素的正确用法

https://blog.csdn.net/Sway_2012/article/details/7768040

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐