文章目录
问题处理记录
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每次扩容为原来的两倍,对小对象来说执行效率高,但如果遇到大对象,执行效率就低了。
优点
- 不指定一块内存大小的数组的连续存储,即可以像数组一样操作,但可以对此数组进行动态操作。通常体现在push_back() pop_back()
- 随机访问方便,即支持[ ]操作符和vector.at()
- 节省空间。
缺点
- 在内部进行插入删除操作效率低。
- 只能在vector的最后进行push和pop,不能在vector的头进行push和pop。
- 当动态添加的数据超过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;
}
注意事项:
- 多线程操作时,需要添加线程锁对数据进行保护;
- 但凡使用了迭代器的循环体,都不要向迭代器所属的容器添加元素;
应用场景
参考资料:
https://www.cnblogs.com/zhonghuasong/p/5975979.html
https://www.cnblogs.com/skyfsm/p/6934246.html