目录
什么是vector
vector的介绍
模板的声明方式
vector的基本操作
push_back
insert
erase
遍历vector
小明爱数列-练习题
思路
什么是vector
vector的介绍
和我一样,我猜你们看到题目时心里都会产生一个疑问"什么是vector?(大佬除外)".vector其实是c++中的一种容器.总而言之,vector就是种特殊的"数组".什么样的数组呢?不定长数组!
不仅如此,他还把一些常规操作封装在了vector内部.
如果说栈是个弹夹,队列就是队列,那么vector就像个贪吃蛇(我的比喻没错吧),不定长度(真的和贪吃蛇的特征很相似)
当然,你们也可以把vector理解成队列的衍生类别(bushi).
其实vector和队列本质上几乎是没有相同的,我只是为了你们好理解(憋屈).
例如: v 是一个vector,和队列,栈一样,我们可以读取他的长度,改变他的大小,删除一个元素,在尾部添加一个元素,判断容器是否为空……一系列的作用
模板的声明方式
由于vector是一个模板,所以我们需要声明一个vector,声明方式如下:
vector<int> v;
vector<double> vd;
vector<char> vc;
vector<int> v;相当于声明一个int类型的数组: int v[];
vector<double> vd;相当于声明一个double类型的数组: double vd[];
vector<char> vc; 相当于声明一个char类型的数组: char vc[];
相比较于普通的数组,vector有点那是只多不少:长度可变,内存动态分配,封装了许多的函数,可以删除插入选择……
接下来,我们来判断一下:
之所以vector的长度可变,是因为他一上来就申请了一个内存超级大的数组来保存数据,虽然你只在这里面使用了一小部分.
这句话对吗?大错特错!!!
vector的长度可变,是因为你加一个数进去,vector的长度就会增加,所以并不是说他一上来就申请了一个超级大的数组(内存:你礼貌吗?) vector 内部包括了一个用来记录数据的数组,当我们不断向 vector 中增加元素时,这个数组也有空间用完的时候,这时 vector 内部会申请一个更大的新的数组,并将原数组中的数据复制到新数组中,之后替换原数组,这就是 vector 长度可变的秘密。
vector的基本操作
vector的函数以及其实现功能如下:
vector<int> v
v.clear() //移除容器中所有数据。
v.empty() //判断容器是否为空。
v.erase(pos) //删除pos位置的数据
v.erase(beg,end) //删除[beg,end)区间的数据
v.front() //传回第一个数据。
v.insert(pos,elem) //在pos位置插入一个elem拷贝
v.pop_back() //删除最后一个数据。
v.push_back(elem) //在尾部加入一个数据。
v.resize(num) //重新设置该容器的大小
v.size() //回容器中实际数据的个数。
v.begin() //返回指向容器第一个元素的迭代器
v.end() //返回指向容器最后一个元素的迭代器
接下来,我们来讲几个比较重要的函数
push_back
push_back是vector最常用的函数之一,其作用就像是在vector的末尾添加一个新的元素(所以呢,push_back是有返回值的),感觉和队列里的push一模一样(没戳).
我们来举个栗子,定义一个vector<int> v;原本v数组里的长度为4(假设的),如果我们v.push_back(5).后,此时序列的长度就变成了5,最后一个元素是v[4],也就是5,vector的下标也是从0开始计算的.
vector<int> v
v.push_back(5);//在末尾添加一个5
insert
insert()和push_back()不同,后者只能把新的元素添加在末尾,而insert却可以把新的元素放在指定的位置.那是不是insert可以完全代替push_back()呢?不不不!!别看insert比push_back厉害,两者的执行效率却截然不同.
对于insert() 操作,比如我们将元素放到位置3,则原来在位置3上的元素会向后移动一位,来到位置4,当然这样又会导致原来在位置4的元素也需要后移,因此insert() 在位置 3,会让3在内以及后面所有的元素都移动1位,效率比较低。
vector<int> v;
v.insert(v.begin()+3,128);
//将128插入到第三个下标(第四个元素)
erase
erase()的作用是从vector当中删除元素,erase可以用来删除某一个元素,也可以来删除某一段元素.删除某一个元素时,给出来的参数是一个位置,这个位置不是简单的数字(像1,2,3,4之类的),他们是可以通过用begin()和end()计算出来的.
比如说我想删除下标为5的元素时,我们需要编写的函数的参数不是v.erase(5),而是v.erase(v.begin(5));如果你想删除一段数字的话就要带上开始位置和结束位置.
接着我们通过一个代码来理解一下以上程序的调用格式:
#include <bits/stdc++.h>
using namespace std;
vector<int> c;
int main(){
//顺序访问
for(int i=0;i<10;i++)
c.push_back(i); //将数字 i 放在最后位置
c.erase(c.begin()+5); //删除下标为5的元素
c.insert(c.begin()+2,11); //把11插入到下标为2的位置
//遍历并输出所有数字
for(int i=0;i<c.size();i++)
cout<<c[i]<<" ";
return 0;
}
结果运行如下:
0 1 11 2 3 4 6 7 8 9
从这个结果我们可以看到erase删除了5;
而insert又将11插入到了1和2之间;
不论是 insert还是erase,都需要begin和end来定位.
遍历vector
接下来我们来学习vector的遍历.
众所周知,数组是可以遍历的,那么vector可不可以遍历呢?当然可以啦,只不过和普通数组的遍历方式有点不一样罢了.
遍历vector的方式有两种
1.直接访问
2.迭代器访问
接着我们放一段代码,生动的教会了大家如何遍历vector
#include <bits/stdc++.h>
using namespace std;
vector<int>obj;
int main(){
//顺序访问
for(int i=0;i<10;i++)
obj.push_back(i);
cout<<"直接利用下标:";
for(int i=0;i<obj.size();i++)//方法一
cout<<obj[i]<<" ";
cout<<endl;
cout<<"利用迭代器:";
//声明一个迭代器,来访问vector容器,作用:遍历或者指向vector容器的元素
vector<int>::iterator it;
for(it=obj.begin();it!=obj.end();it++)
cout<<*it<<" ";
return 0;
}
输出结果不用看了都是一样的:
直接利用数组:0 1 2 3 4 5 6 7 8 9
利用迭代器 : 0 1 2 3 4 5 6 7 8 9
对于二维的vector初始化我们还是需要注意一下的.直接使用:
vector<vector<int>> v
定义出来的是长度为0的二维数组.现在的二维数组我们没有办法访问他,当然push_back也不行,同时要注意定义的时候两个>符号一定要用空格隔开, 不然编译器会认为是输入输出流的符号。
二维数组定义的方式一般有两种:
//方法一:
int N=5,M=6;
vector<vector<int>>obj(N); //定义二维动态数组大小5行
for(int i=0;i<obj.size();i++) //动态二维数组为5行6列,值全为0
obj[i].resize(M);
//方法二:
vector<vector<int>>obj2(N,vector<int>(M)); //定义二维动态数组5行6列
二维数组的本质是vector当中的vector.与之前学的二维数组不同,每一个vector大小都可以不同.
接下来我们来看一道题:
小明爱数列-练习题
小明非常喜欢数列,于是他提出了一个关于数列的问题。他拿到一个长度为 𝑛n 的数列,之后对这个数列进行了两种操作:
第一种:D x
表示删除数列第 x 位置的一个数字,后面的数字向前移动(若 x> 此时数列长度则操作无效);
第二种:Z x y
表示在数列的第 x 位置插入一个数字 y,后面的数字向后移动(若x>此时数列长度则在数列末尾插入 y);
经过k次这两种操作以后,小明想要知道现在的数列是什么,聪明的你可以帮助小明解决这个问题吗?
输入格式
输入包括k+2行数据; 第一行包括两个数n,k,分别表示数列中数的个数以及操作的次数,其中1=<k<=n<5000; 第二行n个数表示该数列的n个数,以空格隔开,其中任意数ai为int范围内的整数; 第三行到第k+2行,每行一个操作,格式见题面描述。
输出格式
输出包括两行; 第一行一个数m,表示全部操作之后数组的长度; 第二行m个数,表示当前的数组。
输入样例
4 3
4 5 2 1
Z 3 3
Z 0 1
D 2
输出样例
5
1 4 2 3 1
数据范围
对于10%的数据,1 <= n <= 4; 对于50%的数据,1 <= n <= 1024; 对于100%的数据,1 <= k<= n <=5000,且ai,x,y是int范围内的整数。
样例解释
初始数组为(4 5 2 1)
执行完Z 3 3得到(4 5 2 3 1)
执行完Z 0 1得到(1 4 5 2 3 1)
执行完D 2得到(1 4 2 3 1)
这道题是一道很明显用vector做的题,话不多说,我们直接上思路:
思路
调用vector 提供的标准函数操作数据即可.D对应 erase ,Z 对应insert.需要特判D和Z操作对应的位置,如果insert 的位置大于vect.size() ,加到最后就好,如果D的位置大于等于 vect.size() ,则不做操作。