vector的学习

发布时间 2024-01-11 18:37:03作者: emopawa

经历的近一年的学习,终于算是想起来了还有这个博客,那终于开始重新拾起,进行一个stl的学习

标准模板库

在C++标准库中,只需要#include头文件,便可以引用
STL标准库分为几个大类,这篇文章只简要介绍vector

vector

什么是vector?我们可以把vector简单的理解为是一个比unsigned long long还要更大的数组,但这并不意味着他占用的空间会很大,事实上,vector数组的大小是在变化着的,这取决于你给他塞入的数据大小。

要使用vector类型,我们需要以下头文件

#include<vector>

vector的定义

vector遵循以下的方式定义:

vector<数据类型> 变量名

数据类型除了常见的int,float,double,long以及long long,ull之外,还可以是STL容器类型vector,queue,set:

vector<int> a;
vector<double> a;
vector<string> a;
vector<long long> a;
vector<vector<int> > a;

vector本身就可以视为一个一维数组,如果在这基础上再开数组,那就是一个二维数组
如:

vector<int > a[n];

访问vector

vector的访问如同数组一般,直接使用下标即可访问:

#include<vector>
int mian()
{
	std::vector<int > a;//定义vector
	a.push_back(114514);//向vector中插入114514;
	cout<<a[0];//访问,输出a[0]=1;
}

输出如下:

114514

同时,stl非常酷炫的一点在于,他有着自己独特的访问方法——迭代器(iterator)

迭代器的使用方法如同指针一样:

 vector<类型名>::iterator 变量名;

例子也很好理解:

vector<int >::iterator itera;

但由于本人不是很会使用迭代器,故先放置一边

vector的常见函数

在stl中,常见的函数有以下几个:

  • .push_back();
  • .pop.back();
  • .size();
  • .clear();
  • .insert();
  • .erase();

push_back()

push_back()的意思非常好理解,他事实上就是把向vector中插入一个元素到vector的末尾

int n,x;
vector<int > a;
for(int i=1;i<=n;i++)
{
	a.push_back(x);//把n插入数组
}

pop_back()

pop_back()这个操作可以理解为push_back()反面,即将一个元素从vector中弹出

int n,x;
vector<int > a;
for(int i=1;i<=n;i++)
{
	a.push_back(x);
	cout<<a[i]<<" ";
}
cout<<endl;
a.pop_back();
for(int i=1;i<=n;i++)
{
	cout<<a[i]<<" ";
}

假设输入为:

1 2 3 4 5

操作后是:

1 2 3 4 5//原本的数列
、1 2 3 4 //pop之后的数列

size()

这个函数顾名思义,就是查询现在vector的大小(所含元素的个数)

int n,x;
vector<int > a;
for(int i=1;i<=n;i++)
{
	a.push_back(x);//把n插入数组
}
cout<<a.size()<<endl;//输出vector大小

假设输入为:

1 2 3 4 6 

输出为:

5

clear()

clear()的作用主要是一键清除vector中的所有元素(全杀了)

int n,x;
vector<int > a;
for(int i=1;i<=n;i++)
{
	a.push_back(x);
	cout<<a[i]<<" ";
}
cout<<endl;
a.clear();
for(int i=1;i<=n;i++)
{
	cout<<a[i]<<" ";
}

假设输入为:

1 2 3 4 5 

将不会输出任何东西,因为这个vector已经被清空了

insert

insert(需要插入的位置,需要插入的元素)

push_back()不同的地方是,他没有push_back()那么粗暴无脑的往最后面插入元素,他是先选择vector中的一个位置,在这个位置插入元素

int n,x;
vector<int > a;
for(int i=1;i<=n;i++)
{
	a.push_back(x);
	cout<<a[i]<<" ";
}
cout<<endl;
insert(a.begin()+3,1919810)//将1919810插入到数列的第3位
for(int i=1;i<=n;i++)
{
	cout<<a[i]<<" ";
}

假设输入为:

1 2 3 4 5 6 

输出为:

1 2 1919810 3 4 5 6

erase()

正如push_back()有一个反义词叫pop_back(),insert()也有自己对应的反义词erase(),他的作用是用来删去指定位置的元素
erase不止可以删除一个元素,也可以删除一个区间的元素

删除一个元素:
erase(元素);
删除一个区间的元素:
erase(左区间,右区间);

注意:这里的区间是左闭右开的
这样便能删除这个区间的元素

vector的常见用途

1.vector用来储存数据的优势在于,他的数组大小是动态变化的,可以较高效的节省空间
2.邻接表存图

vector练习题与解析

洛谷B3665 小清新数据结构题

题目描述

给定 \(n\) 条数据,第 \(i\) 条数据有 \(s_i\) 个数,依次记为 \(a_{i, 1}, a_{i, 2}, \dots a_{i, s_i}\)

现在有 \(q\) 次询问,每次询问第 \(x\) 条数据的第 \(y\) 个数,即 \(a_{x,y}\) 是多少。

为了避免输出过大,你只需要输出所有询问的答案的按位异或和。

按位异或指的是 C++ 中的「^」运算符。你可以参考「说明/提示」中的代码求出若干个数的按位异或和。

输入格式

第一行是两个整数,表示数据条数 \(n\) 和询问次数 \(q\)

接下来 \(n\) 行,每行依次表示一条数据,每行首先是一个整数,表示本条数据的数字个数 \(s_i\),接下来 \(s_i\) 个整数,依次表示本条数据的每个数字。

接下来 \(q\) 行,每行两个整数 \(x, y\),表示一次查询。

输出格式

输出一行一个整数表示所有询问的答案的按位异或之和。

样例 #1

样例输入 #1

2 2
2 1 2
3 4 5 6
2 2
1 2

样例输出 #1

7

提示

样例 1 解释

第一次询问的结果为 \(5\),第二次询问的结果为 \(2\)。他们做按位异或的结果为 \(7\)

数据规模与约定

对于全部的测试点,保证 \(1 \leq n, q, s_i \leq 3 \times 10^6\)\(0 \leq a_i \lt 2^{32}\)\(1 \leq x \leq n\)\(1 \leq y \leq s_x\),且 \(\sum\limits_{i = 1}^n s_i \leq 5 \times 10^6\),即 \(s_1 + s_2 + \dots + s_n \leq 5 \times 10^6\)

解析

通过对数据的分析,我们很快会发现数据范围中的 \(5e6\)的大小很容易MLE
这时考虑使用动态数组vector

代码

#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
const  int MAXN=5e6;
vector<int > a[MAXN];
int n,q;
int x,y;
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>q;
	for(int i=1;i<=n;i++)
	{
		int op;
		cin>>op;
		{
			for(int j=1;j<=op;j++)
			{
				int f;
				cin>>f;
				a[i].push_back(f);
			}
		}
	}
	int ans=0;
	for(int i=1;i<=q;i++)
	{
		cin>>x>>y;
		ans^=a[x][y-1];
	}
	cout<<ans<<endl;
	return 0;
}

总结

vector在实际使用的意义中,常用于作为动态数组。

挖坑

下一篇大概会讲queue和deque罢