C++知识小屋(5):STL——vector常见函数小结

       STL在C++中起到非常重要的作用,最大的好处就是将常见的数据结构进行了封装,使得我们不需要从底层一步步去实现,使用起来非常方便。C++知识小屋🏠的STL系列旨在将常见STL库的常见函数进行小结,以函数+示例+结果展示的方式作为文章的整体结构。希望能够在用到这些库的时候能够快速上手,熟练地使用它们来解决一些常见的问题。

vector

  • vector可以简单理解为是一个动态扩容的数组,如果我们事先无法知道数组的大小,数组的大小是随机变化的话,一般的做法是创建一个空间很大的数组,但是这种方法很费空间,此时使用vector则非常好。

  • 同其他STL库一样,vector内部也包含了非常多的函数,而我们最常用的无非就是下面几种方法:

    • 如何创建vector对象
    • 如何查看vector对象的元素个数和空间大小
    • 如何对vector对象进行增删改查
    • 如何遍历vector对象内的元素
    • 如何对vector对象进行反转
    • 如何对vector对象进行排序
    • 如何构建二维vector数组
    • 如何创建自定义类型的vector数组并进行运算符重载
    • 如何通过count_if函数选择vector中符合自定义条件的元素个数
    • … …
  • 在程序中,我们需要包含下面的vector库,才能正常使用vector:

#include <vector>

构造vector对象的几种方法

  • 下面列举了四种vector对象的构造方法,分别为:
    1.无参构造函数
    2. 有参构造函数(自己指明空间大小,默认初始化值为0)
    3. 有参构造函数(自己设置空间大小和初始化值)
    4. 拷贝构造函数(用另一个vector对象初始化当前对象)

  • 其中我们最常用的方法为无参构造函数,即直接写一个对象名即可。但由于vector可以动态扩容,即当当前空间不足的时候,会创建一个更大的空间,然后把当前空间的值拷贝过去,这个过程是很费时间的,因此如果我们在初始化的时候预估具体情况指明空间大小,尽可能减少扩容的次数,则能提高vector的效率

  • 我们需要指明vector的对象类型,比如下面的例子我使用的是int类型,当然也可以指定为自定义的类型。

  • 下面我们使用的是迭代器的方式遍历vector对象的元素,迭代器的定义格式如下图。

    • 迭代器支持自加(it++),自减等操作的,因此下面使用了it++的方式来遍历vector
    • A.end()表示迭代器的最后一个元素的后一个位置,其值为空,因此当迭代器指向.end()的时候表示已经遍历完了整个vector。
      在这里插入图片描述
#include <iostream>
#include <vector>
using namespace std;

int main(){
	
	/******************构造vector对象*******************/ 
	
	//第一种构造方法(无参数,默认为空) 
	vector<int> A;
	cout << "第一种构造方法: " << endl;
	for(vector<int>::iterator it = A.begin();it!=A.end();it++){
		cout << char(*it) << " ";	//若不加上char,则会输出数字 
	} 
	cout << endl << endl;
	
	//第二种构造方法(参数1:指定容器的大小 ; 参数2:指定元素的初始化值  ) 
	vector<int> B(5,'P');
	cout << "第二种构造方法: " << endl;
	for(vector<int>::iterator it = B.begin();it!=B.end();it++){
		cout << char(*it) << " ";	//若不加上char,则会输出数字 
	} 
	cout << endl << endl;

	//第三种构造方法(参数1:指定容器的大小,且初始化值默认为0) 
	vector<int> C(5);
	cout << "第三种构造方法: " << endl;
	for(vector<int>::iterator it = C.begin();it!=C.end();it++){
		cout << *it << " ";
	} 
	cout << endl << endl;
	
	/*第四种构造方法(复制构造函数:指定A中的某个区间作为C的元素,注意是左闭右开的原则,
					  最后一个元素不包含,即下面的构造函数包含只有两个元素) */ 
	vector<int> D(B.begin()+1, B.begin()+3);
	cout << "第四种构造方法: " << endl;
	for(vector<int>::iterator it = D.begin();it!=D.end();it++){
		cout << char(*it) << " ";
	} 
	cout << endl << endl;
	
	return 0;
} 

在这里插入图片描述


empty 和 clear 来判断函数是否为空以及清空元素

  • A.empty():返回0或者1,0表示A的元素不为空,1表示A的元素为空
  • A.clear():清空A中的所有元素
  • 下面例子的讲解:
    1. 首先创建了一个空的对象A,通过empty函数得到1,说明其为空。
    2. 将元素1添加进A中,此时再调用empty函数,得到0,说明其不为空,符合事实。
    3. 对A使用clear函数,清空A中的所有元素,再使用empty函数,得到1,说明其为空,符合事实。
#include <iostream>
#include <vector>
using namespace std;

int main(){
	
	vector<int> A;
	
	cout << "A是否为空(0:不为空  1:为空):";
	cout << A.empty() << endl;
	
	A.push_back(1);
	cout << "A是否为空(0:不为空  1:为空):";
	cout << A.empty() << endl;	 
	
	A.clear();
	cout << "A是否为空(0:不为空  1:为空):";
	cout << A.empty() << endl;	 	
		
	return 0;
} 

在这里插入图片描述


push_back 和 pop_back函数进行添加和删除元素

  • A.push_back(i) :在A的末尾加入i元素
  • A.pop_back():删除A的末尾的元素
  • 如果我们使用push_back函数(参数为需要添加的元素值),则可以在vector对象的末尾添加上新的元素,如下面的例子展示了如何在对象A中添加1,2,3三个元素。
#include <iostream>
#include <vector>
using namespace std;

int main(){
	
	vector<int> A;			//创建对象 
	for(int i=1;i<4;i++){
		A.push_back(i);		//添加元素 
	}
	for(vector<int>::iterator it = A.begin();it!=A.end();it++){
		cout << *it << " ";	 
	} 
	cout << endl << endl;	
	
	A.pop_back(); 			//删除一个末尾元素 
	for(vector<int>::iterator it = A.begin();it!=A.end();it++){
		cout << *it << " ";	 
	} 
	cout << endl << endl;	
	return 0;
} 

在这里插入图片描述


运算符[] 和 .at()函数访问元素

  • vector跟数组一样,能使用下标的方式进行元素访问,同时还支持.at()的方式进行访问。
  • 使用下标访问的话不会显示越界访问的错误提示,因此使用.at()函数会更安全。
#include <iostream>
#include <vector>
using namespace std;

int main(){
	
	vector<int> A;			//创建对象 
	for(int i=1;i<4;i++){
		A.push_back(i);		//添加元素 
	}
	for(vector<int>::iterator it = A.begin();it!=A.end();it++){
		cout << *it << " ";	 
	} 
	cout << endl << endl;	
	
	cout << "下标访问: " << A[0] << "  " <<  A[1] << "  " << A[2] << endl; 
	cout << "at函数访问: "  << A.at(0) << "  " << A.at(1) << "  " << A.at(2) << endl;
	return 0;
} 

在这里插入图片描述


insert和erase函数进性插入和删除元素

  • 与前面的push_back和pop_back函数类似,insert和erase能够实现插入和删除元素,但是前者只能在vector的末尾进行操作,而后者能够在任意位置进行操作。
  • 用法讲解:
    • A.insert(A.begin(),100) :表示在A的开头加上100
    • A.erase(A.begin()):表示删除A开头的元素
  • 需要注意的是,如果要删除A的最后一个元素,需要使用A.erase(A.end()-1),因为A.end()表示的是A的最后一个元素的后一个值,而不是最后一个元素。
  • 下面展示了该函数的用法:
#include <iostream>
#include <vector>
using namespace std;

int main(){
	
	vector<int> A;				//创建对象 
	for(int i=1;i<4;i++){
		A.push_back(i);			//添加元素 
	}
	for(vector<int>::iterator it = A.begin();it!=A.end();it++){
		cout << *it << " ";	 
	} 
	cout << endl << endl;	
	
	A.insert(A.begin(),100);	//在第一个元素前插入100 
	A.insert(A.end(),200); 		//在最后一个元素后一个位置的前面插入200(A.end()-1才表示最后一个元素) 
	cout<< "插入元素后的情况:" ; 
	for(vector<int>::iterator it = A.begin();it!=A.end();it++){
		cout << *it << " ";	 
	} 
	cout << endl << endl;	
		
	A.erase(A.begin());			//删除第一个元素 
	A.erase(A.end()-1);			//减去1才表示最后一个元素,否则删除A.end会报错 
	cout<< "删除元素后的情况:" ; 
	for(vector<int>::iterator it = A.begin();it!=A.end();it++){
		cout << *it << " ";	 
	} 
	cout << endl << endl;
				
	return 0;
} 

在这里插入图片描述


使用.size()函数进行vector的遍历

  • 可以看到我们前面的所有例子都是使用迭代器的方式进行元素的遍历,因为这种方法对于很多STL库都适用。但是由于vector支持下标的访问,因此也可以像数组一样进行遍历。
  • 其中A.size()表示A中有多少个元素
#include <iostream>
#include <vector>
using namespace std;

int main(){
	
	vector<int> A;			//创建对象 
	for(int i=1;i<4;i++){
		A.push_back(i);		//添加元素 
	}
	
	//使用数组一样的方式进行访问 
	for(int i=0;i<A.size();i++){	
		cout << A[i] << " ";
	} 
	cout << endl << endl;	
	
	return 0;
} 

在这里插入图片描述


使用reverse函数反转vector

  • 如果我们想反转一个vector,可以使用reverse的方式,而且需要包含下面的algorithm库:
#include<algorithm>
  • 其中reverse(A.begin(),A.end())表示对A进行了反转,下面为具体的例子展示:
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;

int main(){
	
	vector<int> A;			//创建对象 
	for(int i=1;i<4;i++){
		A.push_back(i);		//添加元素 
	}
	
	//使用数组一样的方式进性访问 
	cout << "原来的vector:" ;
	for(int i=0;i<A.size();i++){	
		cout << A[i] << " ";
	} 
	cout << endl << endl;
	
	reverse(A.begin(),A.end());	//对A进行反转
	cout << "反转后的vector:" ;
	for(int i=0;i<A.size();i++){	
		cout << A[i] << " ";
	} 
	cout << endl << endl;		
	
	return 0;
} 

在这里插入图片描述


自定义排序方式进行sort方式排序

  • 与常见的数组一样,vector也能够使用sort进行排序(默认为升序),如果我们想自定义降序排序vector对象,则可以使用下面的方式,其中 sort(A.begin(),A.end(),cmp);表示对A中的全部元素进行cmp规则的排序。
  • 同样,使用sort函数需要导入algorithm的库
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;

//自定义降序排序函数 
bool cmp(const int &a,const int &b){
	return a > b;
}

int main(){
	
	vector<int> A;			//创建对象 
	for(int i=1;i<4;i++){
		A.push_back(i);		//添加元素 
	}
	
	//使用数组一样的方式进性访问 
	cout << "原来的vector:" ;
	for(int i=0;i<A.size();i++){	
		cout << A[i] << " ";
	} 
	cout << endl << endl;
	
	//对A进行cmp方式的降序排序
	sort(A.begin(),A.end(),cmp);
	
	cout << "降序排序后的vector:" ;
	for(int i=0;i<A.size();i++){	
		cout << A[i] << " ";
	} 
	cout << endl << endl;		
	
	return 0;
} 

在这里插入图片描述


使用vector构建二维数组

  • 如果我们要使用vector构建二维数组,则可以用下面的方式定义,注意!后面的两个’>'中间一定要有空格,否则会报错。
vector<vector<int> >A;
#include <iostream>
#include <vector>
using namespace std;

int main(){
	//构造对象A (后面的两个'>'中间一定要有空格,否则会报错) 
	vector<vector<int> >A;
	
	//输入二维数组的两个维度的值 
	int m,n;
	cout << "请输入两个维度的值" << endl; 
	cin >> m >> n;	
		
	//构造A的大小 
	A.resize(m);
	for(int i=0;i<A.size();i++){
		A[i].resize(n);
	}

	//输入A中的每一个元素 
	cout << endl << "请输入每一个元素值: " << endl; 
	for(int i=0;i<A.size();i++){
		for(int j=0;j<A[i].size();j++){
			cin >> A[i][j] ; 
		}
	}
	
	//输出A中的每一个元素 
	cout << endl << "下面输出A的值: " << endl; 
	for(int i=0;i<A.size();i++){
		for(int j=0;j<A[i].size();j++){
			cout << A[i][j] << " "; 
		}
		cout << endl;
	}

	return 0;
} 

在这里插入图片描述


自定义类型的 vector 和 count_if 函数

  • 在前面的例子中,我都是使用普通的类型进行vector的构造,但是在实际应用当中,往往需要与自定义的类型结合起来,因此下面展示如何对自定义类型进行vector的相关操作,结合了自定义排序函数(只需要重载“<”符号即可),输出流重载函数(方便输出)。
    • 下面的例子中重载的排序函数为:先比较x,x小的放前面;若x相等,则y小的放前面
  • 同时使用了count_if函数选择了vector中符合条件的元素的个数。
    • countf_if(A.begin(),A.end(),cmp) :表示在vector A对象中判断有多少个元素符合cmp条件,返回的是符合条件的个数。
    • cmp函数需要自己定义,如下所示,表示只有当x变量大于80才符合条件。
bool cmp(Point A) {
	return A.x > 80;
}
  • 下面的例子展示了上面所说的功能,A中包含四个Point对象,可看到经过排序的最终结果,由于四个对象中x最小的为60,因此x放在了最前面,而对于两个x都为85的元素,则y较小的放在前面。
  • 最后通过count_if函数发现,符合x大于80的条件的元素有三个,因此输出3。
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;

class Point{

	public:
		//两种变量x,y 
		int x,y;		 

		//二合一的构造函数 
		Point(int _x=0,int _y=0){
			x = _x;
			y = _y;
		}
		
		//重载小于函数,用于sort排序 
		friend bool operator < (const Point & A,const Point & B){
			if(A.x != B.x){
				return A.x < B.x;
			}
			return A.y < B.y;
		}
		
		//重载输出流 
		friend ostream & operator << (ostream & o,const Point & A){
			o << A.x << "  " << A.y << endl;
			return o;
		}
	
};

//定义count_if的选择条件为x大于80 
bool cmp(Point A) {
	return A.x > 80;
}

int main(){
	
	vector<Point> A;			//创建对象以及输入数据 
	A.push_back(Point(85,25));
	A.push_back(Point(95,60));
	A.push_back(Point(85,50));
	A.push_back(Point(60,40));
	
	
	
	//使用数组一样的方式进性访问 
	cout << "原来的vector:" << endl;
	for(int i=0;i<A.size();i++){	
		cout << A[i] ;
	} 
	cout << endl << endl;
	
	//对A进行排序 
	sort(A.begin(),A.end());
	
	cout << "排序后的vector(先按x小的在前,再按y小的在前)" << endl;
	for(int i=0;i<A.size();i++){	
		cout << A[i] ;
	} 
	cout << endl << endl;		
	
	//用cmp的原则筛选符合条件的元素的个数大小 
	int num = count_if(A.begin(),A.end(),cmp);
	cout << "符合 x>80 的个数有 :" << num << endl; 
	
	return 0;
} 

在这里插入图片描述


         上面展示了我认为比较常用的vector的方法,如果后面发现一些其他的常用方法的话,以后会进行补充的,也欢迎大家在评论区说说vector的一些常用方法噢🎃!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值