vector的常用用法(STL库)

参考这一篇很详尽C++ vector 容器浅析

vector 翻译为向量, 但是这里使用 “变长数组”的叫法更容易理解,也即 “长度根据需要而自动改变的数组”。 在考试题中,有时会碰到只用普通数组会超过内存的情况, 这种情况使用vector可以解决很多问题。 另外,vector还可以用来以邻接表的方式存储图,这对无法使用邻接矩阵的题目(节点数太多)、又害怕使用指针实现邻接表的朋友是非常友好的。

如果要使用vector ,则需要添加vector的头文件,即 #include<vector> ,  此外还需要在头文件下加上 using namespace std;  

1、vector的定义

单独定义一个vector:

vector<typename>  name;

上面这个定义其实就相当于是一维数组name[SIZE],只不过其长度可以根据需要进行变化,比较节省空间,通俗说了就是“变长数组”。

和一维数组一样,这里的 typename 可以是任何基本类型, 例如int、double、char、结构体等,也可以是STL标准容器,例如vector、set、queue等。

vector<int> name;

vector<double> name;

vector<char> name;

vector<node> name;  //node是结构体类型

vector<int> v1;                            //定义元素为int的向量v1

vector<int> v2(10);                      //指定向量v2的初始大小为10个int元素

vector<double> v3(10,1.23);       //指定v3的10个初始元素的初值为1.23

vector<int> v4(a,a+5);                 //用数组a[0...4]共5个元素初始化v4

 需要注意一点,如果 typename 也是一个STL容器,定义的时候要记得在> >之间加一个空格,否则编译器会把它视作移位操作,导致编译错误。

vector <vector<int> > name;  

可以很容易联想到二维数组的定义,即其中一维是一个数组的数组。那么二维 vector 数组,即Arrayname[]中的每一个元素都是vector。可以把二维vector数组理解为两个维都可变长的二维数组。

定义vector数组的方法:

vector<typename> Arrayname[arraySize];

例如:

vector<int> vi[10];

这样Arrayname[0]~Arrayname[arraySize-1]中的每一个元素都是一个vector容器。

与vector <vector<int> > name 不同的是,这种写法的一维长度已经固定为arraySize,另一维才是“变长”的。

 

2、vector容器内元素的访问

一般有两种方式:通过下标访问和通过迭代器访问。

(1)通过下标访问

和普通的数组一样,对于一个定义为 vector<typename> vi 的vector容器来说,直接访问 vi[index] 即可(如vi[0], vi[1])。

(2)通过迭代器访问

迭代器(iterator)可以理解为一种类似指针的东西,其定义是:

vector<typename> :: iterator it;

这样 it 就是一个 vector<typename> :: iterator 型的变量,其中typename就是定义vector是填写的类型。

vector<int> :: iterator it;

vector<double> :: iterator it;

这样就得到了迭代器it, 并且可以通过 *it 来访问 vector 里面的元素。

例如有这样一个vector容器:

vector<int> vi;

for(int i = 1; i <= 5; i++ ) {

     vi.push_back(i);  //push_back(i) 在 vi 的末尾添加元素i ,即依次添加 1,2,3,4,5

}

可以通过类似下标和指针访问数组的方式来访问容器内的元素:

#include<cstdio>
#include<vector>
using namespace std;

int main(){
	vector<int> vi;
	for(int i=1; i<=5; i++){
		vi.push_back(i);
	}
	
	//vi.begin()为取vi的首元素地址,而it指向这个地址 
	vector<int>::iterator it = vi.begin();
	
	for(int i=0;i<5;i++){
		printf("%5d", *(it+i));  //输出vi[i] 
	}
	return 0;
}

输出结果:

 

从这里可以看出, vi[i]  和 (vi.begin() + i)是等价的

既然上面说到了 begin()函数的作用是为取vi的首元素地址,那么还有end()函数,end() 并不是取 vi 的尾元素地址,而是取尾元素地址的下一个地址。end()作为迭代器的末尾标志,不存储任何元素,这里的begin()和end() “左闭右开”

 

除此之外,迭代器还实现了两种自加操作: ++it  和  it++(自减操作同理),于是有了另一种遍历vector的写法:

#include<cstdio>
#include<vector>
using namespace std;

int main(){
	vector<int> vi;
	for(int i=1;i<=5;i++){
		vi.push_back(i);
	}
	
	//vector的迭代器不支持 it<vi.end() 写法,因此循环条件只能用 it!=vi.end()
	for(vector<int>::iterator it=vi.begin(); it!=vi.end(); it++){
		printf("%5d",*it);
	}
	
	return 0;
}

最后需要指出,在常用的STL容器中,只有vector和string中,才允许使用vi.begin()+3这种迭代器加上整数的写法。

 

3.vector常用函数

(1)push_back( )

push_back( )就是在vector后面添加一个元素x,时间复杂度为O(1)。

示例如下:

#include<cstdio>
#include<vector>
using namespace std;

int main(){
	vector<int> vi;
	for(int i=1;i<=5;i++){
		vi.push_back(i);
	} 
	
	for(int i=0;i<vi.size();i++){ //vi.size()返回vi中元素的个数 
		printf("%5d",vi[i]);  //这里直接通过下标访问 
	}
} 

 

(2)pop_back()

pop_back()用于删除vector的尾元素,时间复杂度为O(1)。

示例如下:

#include<cstdio>
#include<vector>
using namespace std;

int main(){
	vector<int> vi;
	for(int i=1;i<=5;i++){
		vi.push_back(i);
	} 
	
	vi.pop_back(); //删除vi的尾元素5 
	
	for(int i=0;i<vi.size();i++){ //vi.size()返回vi中元素的个数 
		printf("%5d",vi[i]);  //这里直接通过下标访问 
	}
} 

(3)size()

size()用来获取vector中元素的个数,时间复杂度为O(1)。size()返回的是unsigned类型,不过一般来说%d也不会有什么问题。

 

(4)clear()

clear()用来清空vector中的所有元素,时间复杂度为O(N)。

#include<cstdio>
#include<vector>
using namespace std;

int main(){
	vector<int> vi;
	for(int i=1;i<=5;i++){
		vi.push_back(i);
	} 
	
	vi.clear();  //清空vi中的所有元素 
	
	printf("%d",vi.size());  

} 

(5)insert()

insert(it,x)用来向vector的任意迭代器it处插入一个元素x,时间复杂度为O(N)。

#include<cstdio>
#include<vector>
using namespace std;

int main(){
	vector<int> vi;
	for(int i=1;i<=5;i++){
		vi.push_back(i);
	}
	vi.insert(vi.begin()+2,-99); //将-99插入到vi[2]的位置
	for(int i=0;i<vi.size();i++){
		printf("%5d",vi[i]);
	} 
}

输出结果:

 

(6)erase( )

erase( )有两种用法:删除单个元素、删除一个区间内所有元素,时间复杂度均为O(N)。

①删除单个元素

erase(it),即删除迭代器为it处的元素。

示例:

#include<cstdio>
#include<vector>
using namespace std;

int main(){
	vector<int> vi;
	for(int i=5;i<=9;i++){
		vi.push_back(i); //插入5,6,7,8,9 
	} 
	
	vi.erase(vi.begin()+3); //删除元素 8 
	
	for(int i=0;i<vi.size();i++){ //vi.size()返回vi中元素的个数 
		printf("%5d",vi[i]);  //这里直接通过下标访问 
	}
} 

 

②删除一个区间内的所有元素

erase(first,last);  其中first为需要删除的区间的起始迭代器,而last则为需要删除的区间的末尾迭代器的下一个地址,也即为删除左闭右开的区间 [first,last) 。

示例:

#include<cstdio>
#include<vector>
using namespace std;

int main(){
	vector<int> vi;
	for(int i=5;i<=9;i++){
		vi.push_back(i); //插入5,6,7,8,9 
	} 
	
	vi.erase(vi.begin()+1, vi.begin()+4); //删除元素 6,7,8   //注意右边是开的 
	
	for(int i=0;i<vi.size();i++){ //vi.size()返回vi中元素的个数 
		printf("%5d",vi[i]);  //这里直接通过下标访问 
	}
} 

如果要删除这vector里面的所有元素,正确的写法是 vi.erase(vi.begin(), vi.end()),当然最方便的清空是 vi.clear();

 

4、vector的常见用途

(1)存储数据

①vector本身可以作为数组使用,而且在一些元素个数不确定的场合,可以很好的节省空间。

②有些场合需要根据一些条件把部分数据输出在同一行,数据之间中空格隔开,由于输出数据的个数是不确定的,为了更方便的处理最后一个满足条件的数据后面不输出空格,可以先用vector记录所有需要输出的数据,然后一次性输出。

 

(2)用邻接表存储图

使用vector实现邻接表,可以替代指针的写法。

 

这里要补充一下vector的构造函数

  • vector():创建一个空vector
  • vector(int nSize):创建一个vector,元素个数为nSize
  • vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
  • vector(const vector&):复制构造函数
  • vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值