STL之vector用法
概述
- STL提供3种顺序容器:vector、list、deque。vector和deque都是基于数组的,list实现链表数据结构。
- vector是STL最常用的容器之一。vector是动态数组,是可变长度的数组。
- vector对于末尾插入数据十分有效(增加新项目时相应增长),而在中间插入或删除的成本很高(插入或删除元素之后的整个vector部分都要移动)。
- vector和原始数组相同点:具有连续内存地址,因此vector类对象可以用重载下标运算符[ ]快速索引访问;下标不进行自动范围检查
- vector类与原始数组不同点:vector可以相互赋值(原始数组的数组名是常量指针,不能作为赋值目标)。vector类通过成员函数at提供范围检查的功能。
- vector容器最适用于达到性能最好的随机访问。
- 对于vector,同时插入多个元素比一次插入一个要快。
- 当vector的内存用尽时,vector自动分配更大的连续内存区,将原先的元素复制到新的内存区然后释放旧的内存区。
- 如果在已满的vector中添加元素,vector自动增加长度,有些版本可能自动将vector的长度翻倍。
- 虽然随机访问迭代器支持<,但是最好用!=和end()来测试容器末尾!
- vector支持随机访问迭代器,即vector可以使用下表内所有的迭代器操作。
具体用法
0. 头文件
#include<vector>
1. 声明和初始化
//声明vector类的实例vec,存放int值,生成了一个长度为0的空vector,容量capacity为0
vector<int>vec;
//声明一个int类型的二维向量vec
vector<vector<int>>vec;
//声明一个int类型的一维向量vec,并将{1,2,3,4}赋值给vec
vector<int>vec = {1,2,3,4};
//生成一个向量vec2,将vec复制给vec2
vector<int>vec2 = vec;
或 vector<int>vec3(vec);
//生成一个向量vec,将数组a的a[0]到a[4]的内容复制给vec
vector<int>vec(a,a+5);
或 vector<int>vec4(&a[0], &a[4]);
//生成一个向量vec,将向量vec0从vec[0]到vec[2]的内容赋值给vec
vector<int>vec(vec0.begin(),vec0.begin()+3);
//生成一个向量vec,将v大小设为10,且每个元素都为设置为0(默认)
vector<int>vec6(10);
//生成一个向量vec,将大小设为10,且每个元素都为设置为5
vector<int>vec7(10,5);
//将vec清空,然后添加2个元素,每个元素都赋值为10
vec.assign(2, 10);
//将vec[2]赋值为10
vec[2]=10;
或 vec.at(2) = 10;
//声明二维向量v1,将两个一维向量v2,v3赋值给v1
vector<vector<int>>v1;
vector<int>v2 = {1,7,8,9};
vector<int>v3 = {2,10,45,1};
v1.push_back(v2);
v1.push_back(v3);
2. 常用函数(查询)
2.1 empty()
vec.empty(); //返回值bool类型,若vec为空,则返回true
2.2 size()
vec.size(); //返回值为int类型,vec当前存放的元素的个数
2.3 capacity()
vec.capacity(); //返回不增加内存时vec可以存放的元素个数,vec.capacity()>=vec.size()
2.4 front()
条件:vec不能为空,否则vec.front()结果是未定义!
vec.front(); //返回vec数组最前面的元素,即vec[0]
2.5 back()
条件:vec不能为空,否则vec.back()结果是未定义!
vec.back(); //返回vec数组最末尾的元素,即vec[vec.size()-1]
2.6 at() 和 下标运算符[ ]
用法与下标运算符相似。但是at()会检查是否越界,若越界会抛出out of range异常,而[ ]则不会检查
//访问第3个数
vec.at(2);
vec[2];
//将第3个数赋值为10
vec.at(2)=10;
vec[2]=10;
2.7 迭代器
vector的迭代器通常实现为vector元素的指针。
//开始指针(正向)
vec.begin()
//结束指针(正向),指向vec最后一个元素的后一位
vec.end()
//开始指针(逆向)
vec.rbegin()
//结束指针(逆向),指向vec最后一个元素的后一位
vec.rend()
//常量开始指针(正向),不能通过该指针来修改所指内容
vec.cbegin()
//常量结束指针(正向),不能通过该指针来修改所指内容,指向vec最后一个元素的后一位
vec.cend()
2.8 输出
//迭代器,顺序访问
for (vector<int>::iterator p = nums.begin(); p != nums.end(); p++)
cout << *p << " ";
//输出迭代器,copy算法
ostream_iterator<int> output(cout, " ");
copy(vec.begin(),vec.end(),output);
cout<<endl;
//迭代器,逆序访问
for (vector<int>::reverse_iterator p = nums.rbegin(); p != nums.rend(); p++)
cout << *p << " ";
//下标,顺序访问
for (int i = 0; i < vec.size(); i++)
cout << vec[i] << " ";
//下标,逆序访问
for (int i = vec.size()-1; i >=0; i--)
cout << vec[i] << " ";
//若是二维vector,注意传入参数是按值传递(不是&nums)因此在函数里对向量的修改不影响真正的向量的元素。顺序访问
void display_vector_two(vector<vector<int>> nums) {
while (!nums.empty()) {
for (vector<int>::iterator p = nums.front().begin(); p != nums.front().end(); p++)
cout << *p << " ";
cout << endl;
nums.erase(nums.begin()); //每次输出一排就删除,指针指向下一排继续输出
}
}
//还有一个基础的类似二维数组a[ ][ ]的输出方法,用下标运算符[ ]来输出,顺序访问
void display_vector_two(vector<vector<int>> nums) {
for (int i = 0; i < nums.size(); i++) {
for (int j = 0; j < nums[i].size(); j++) {
cout << nums[i][j] << " ";
}
cout << endl;
}
}
3. 常用函数(操作)
3.1 push_back()
//在末尾插入元素2
vec.push_back(2);
3.2 pop_back()
//删除末尾元素
vec.pop_back();
3.3 assign()
//将vec清空,然后添加2个元素,每个元素都赋值为10
vec.assign(2, 10);
//将vec清空,然后将vec1[0]到vec1[3]复制给vec。相当于拷贝函数
vec.assign(vec1.begin(),vec1.begin()+4)
2.4 insert()
//在第二个元素前插入10
vec.insert(vec.begin()+1,10);
3.5 erase()
//删除vec[0]的元素
vec.erase(vec.begin());
//删除从vec[0]到vec[4]的元素
vec.erase(vec.begin(),vec.begin()+5);
3.6 swap()
//交换向量vec和向量vec1的元素
vec.swap(vec1);
3.7 clear()
//清空向量
vec.clear();
3.8 resize()
//重置向量的大小为10
vec.resize(10);
4. 常用算法
4.0 头文件
#include<algorithm>
4.1 copy()
//将vec1[0]到vec1[3]的内容复制给vec
copy(vec1.begin(),vec1.begin()+4,vec);
4.2 reverse()
//元素翻转
reverse(vec.begin(), vec.end());
4.3 sort()
//排序默认(从小到大)
sort(vec.begin(), vec.end());
//排序(从大到小)
sort(vec.begin(), vec.end());
reverse(vec.begin(), vec.end());
//排序(从大到小),自己写一个判断条件给sort作为第三个参数
bool Comp(const int& a, const int& b) {
return a > b;
}
sort(vec.begin(), vec.end(), Comp);
5.实际使用
5.1 二维数组
//若已知n行、m列:声明一个n行m列的二维数组v1[][]
vector<vector<int>> v1(n,vector<int>(m));
//若已知n行:声明一个n行0列的二维数组v2[][]
vector<vector<int>> v2(n); //此时列数为0
for (int i = 0; i < n; i++) { //得知列数后,修改列数为m
v2[i].resize(m);
}