1.vector的常见用法
vector翻译为向量,但是用“长短根据需要而自动改变的数组”更容易记忆。如果要使用vector,则需要用到头文件#include <vector>,另外还需要using namespace std; 才可以使用。
PAT中的相关题目有(代码见下方):
1039 Course List for Student (25 分)
1047 Student List for Course (25 分)
1.1 vector的定义:vector<typename> name
例如:vector<int> name vector<double> name等
引申:由此容易联想到二维数组的定义,初学者可以把二维vector数组当做两个维都可以变长的二维数组来理解更方便。因为vector<double> name本身就是一个数组,那么vector的二维数组就变成了vector<typename> Arrayname[arraySize]。这样ArraySize[0]~ArraySize[arraySize-1]中每一个都是一个vector容器。vector二维数组使用是这样的:Arrayname[x][y]。
1.2 vector容器内元素的访问
(1)下标法访问:如vector<int> vi,访问vi[index]即可(如vi[1],vi[2]),但是这样的缺点也很明显,即访问除了0~vi.size()-1以外的元素会出错,失误了vector容器的灵活性。
(2)通过迭代器访问:迭代器(iterator),其定义是vector<typename>::iterator it; 如(vector<int>::iterator it=vi.begin();),从括号里的例子可以看出,这里的vi[i]和*(vi.begin()+i)是等价的。另外值得注意的一点是,与begin()正好代表第1个(数组中标记为0),end()并不是取伪元素,而是取尾元素的下一个地址,这是不同的。
1.3 vector的函数
(1)push_back():顾名思义,push_back(x)就是在vector后面添加一个元素x,示例:
for(int i=0;i<=3;i++){
vi.push_back(i); //将0 1 2 3 依次插入vi的末尾,可以输出0123
}
(2)pop_back():用来删除vector的尾元素,示例:
for(int i=0;i<=3;i++){
vi.push_back(i); //将0 1 2 3 依次插入vi的末尾,可以输出0123
}
vi.pop_back(); //删除了3
(3)size():用来获取vector的元素,示例:
vi.size(); //获得vector容器元素的个数
(4)clear():用来清除vector中的所有元素,示例:
vi.clear(); //清除vector容器的所有元素
(5)insert():insert(it,x);就是在任意迭代器it处插入一个元素x,示例:
for(int i=0;i<=3;i++){
vi.push_back(i); //将0 1 2 3 依次插入vi的末尾,可以输出0123
}
vi.insert(vi.begin()+2,-1); //0 1 -1 2 3
(6)erase():删除单个元素或者删除一个区间内的所有元素,示例:
for(int i=0;i<=3;i++){
vi.push_back(i); //将0 1 2 3 依次插入vi的末尾,可以输出0123
}
vi.erase(vi.begin()+2); //删除位置在2号为的元素
vi.erase(vi.begin()+1,vi.begin()+3);//删除位置在1~2号位的所有元素
现在附上两道PAT的代码:
A1039 需要用到的是vector的二维数组存储方式和表达方式:
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string.h>
#include <iostream>
using namespace std;
const int N=40010; //总人数
const int M=26*26*26*10+10; //名字的上限
vector<int> selectCourse[M]; //每个学生选择的课程编号
int getID(char a[]){
int id=0;
for(int i=0;i<3;i++){
id=id*26+(a[i]-'A'); //我曾在这里犯了错误,误以为id*10的,导致段错误,也就是数组溢出了
}
id=id*10+(a[3]-'0');
return id;
}
int main(){
char name[5];
int m,n;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int course,x;
scanf("%d%d",&course,&x);
for(int j=0;j<x;j++){
scanf("%s",name);
int id=getID(name);
selectCourse[id].push_back(course); //这里就是vector的二维数组构成现场,将此事id这个学生选的课记录在后面,selectCourse本身也是数组
} //可以认为selectCourse纵向分布,course在其后面横向分布
}
for(int i=0;i<n;i++){
scanf("%s",name);
int id=getID(name);
sort(selectCourse[id].begin(),selectCourse[id].end());
printf("%s %d",name,selectCourse[id].size());
for(int j=0;j<selectCourse[id].size();j++){
printf(" %d",selectCourse[id][j]); //vector二维数组的输出,就是输出每个学生之后选的课
}
printf("\n");
}
return 0;
}
A1047 也是考察vector二维数组(注意二者的不同):
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <iostream>
using namespace std;
const int N=40010;
const int M=2510; // 我在这里也犯了溢出错误,给数组的空间不够
char name[N][5];
vector<int> course[M];
bool cmp(int a,int b){
return strcmp(name[a],name[b])<0;
}
int main(){
int n,m,x,courseID;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%s%d",name[i],&x);
for(int j=0;j<x;j++){
scanf("%d",&courseID);
course[courseID].push_back(i); //和A1039类似,这里也是存储的vector二维数组,但是这里反过来,以课程为纵轴,学生为横轴
} //都是数字,课程编号和名字位置编号
}
for(int i=1;i<=m;i++){
printf("%d %d\n",i,course[i].size());
sort(course[i].begin(),course[i].end(),cmp);
for(int j=0;j<course[i].size();j++){
printf("%s\n",name[course[i][j]]); //通过课程编号和名字位置编号,可以得出名字
}
}
return 0;
}