STL-vector向量
STL-vector向量
vector数组是一个能 存放任意数据类型(类,结构,普通变量类型等)的动态数组,
在数据结构中就相当于顺序储存的线性表,寻找元素非常快,但是插入元素的时间却很大。
与其它动态序列容器相比(deques, lists and forward_lists), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效
和普通数组一样可以通过下标索引来进行访问
list是一个双向链表,在同一个为止插入大量的数据时速度很快,但是查找的速度就会慢很多
1.头文件
#include<vector>
using namespace std;
2.构造函数
vector<int> vec; // 空的vector,只是一个列表的头,里面没有元素
vector<string> vec;
vector<int> vec1 = {1,3,4,5,6};
vector<int> vec1(4, 100); // 初始化一个具有4个元素的vector,每个元素的值都是100
vector<int> vec2 (vec.begin(), vec.end()); // 通过其他vector的迭代器的方式,进行拷贝复制初始化
vector<int> vec3 (vec); // 直接对其他vector的拷贝复制
//二维初始化
vector<vector<int>> vars(size, vector<int>(size, 0)); // (size,size)的矩阵,元素全部是0
//用vector构建二维数组
vector<vector<int>> matrix;
vector<int>a;
a.push_back(1);
a.push_back(3);
a.push_back(1);
matrix.push_back(a);
//或者用下面的方法
int i,j;
vector<vector<int>> array(5);
for (i = 0; i < array.size(); i++)
array[i].resize(3);//这里一定要使用resize其相当于每行的元素数并已经初始化过了
3.索引存取元素
索引其元素和索引一般的数组元素相似,使用下标或者 at()
operator[index];//类似数组中的[],返回索引index所指向的数据
at(int index);//用at函数来返回索引index所指向的数据
front();//返回容器中的第一个数据
back();//返回容器中最后一个元素
vector<int> vec1 = {1,3,4,5,6};
vec1[1];
// 直接索引,针对多维度的也是一样
输出是3
vec1[1] = 0;
//直接可以修改
输出是0
vec1.at(1) = 1;
// 也可以通过函数索引
输出是1
vec1.back();
// 获取vector的最后一个元素
输出是6
# 输出最小值及索引
*max_element(vec.begin(),vec.end());
*min_element(vec.begin(),vec.end());
# 输出最大最小值索引
max_element(vec.begin(),vec.end())-vec.begin();
min_element(vec.begin(),vec.end())-vec.begin();
4.遍历元素
方法一、索引遍历
vector<int> vars;
int vsize = vars.size();
for (int i = 0; i < vsize; ++i){
cout << vars[i];
}
方法二、迭代器变量
vector<int> vars = {1,3,5,6,7,8};
for (vector<int>::iterator it = vars.begin(); it != vars.end(); it++){
cout<< *it <<""; // 遍历每一个元素
}
指定区间中的遍历;
vector<int> vars = {1,3,5,6,7,8};
for (vector<int>::iterator it = vars.begin()+1; it != vars.end()-1; ++it){
*it = 10; // 遍历每一个元素
}
方法三、使用auto关键字
for (auto it = vars.begin(); it != vars.end(); ++it){
cout << " "<< *it; // 遍历每一个元素
}
//多维度
for (int i = 0; i < vec.size(); i++)
{
for (int j = 0; j < vec[0].size(); j++)
cout << vec[i][j] << " ";
cout << endl;
}
#include <vector>
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
vector<int> vars = {1, 3, 5, 6, 7, 8};
vector<vector<int>> vec = {{1, 2, 3}, {4, 5, 6}};
for (auto iter = vec.begin(); iter != vec.end(); iter++)
{
vector<int> vec_tmp = *iter;
for (auto it = vec_tmp.begin(); it != vec_tmp.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
return 0;
}
4.capacity 相关
1、vec.size();
//元素个数
2、vec.max_size();
//vector 可允许的最大容量
3、vec.resize();
// 改变容器可以容纳元素的个数,
4、vec.capacoty();
//理论容量
5、vec.empty();
//返回是否为空,true, false;
6、vec.reserve();
// 使得capacity至少能容纳n个元素。
7、vec.shrink_to_fit();
//减小capacity,使其与容器大小相同
5.插入元素
vec.push_back(同类型量);作用是在vector的末尾插入新元素
insert()第一个参数为迭代器,作用为在迭代器前面插入新元素
insert()第一个参数为迭代器,作用为在迭代器前面插入新元素
尾插法
vector<int> vars ;
vars.push_back(10);
insert插入法
vector<int> vars = {1,2,3,4,5};
vars.insert(vars.begin(), 100);
// 插入单个元素,在vars的第0元素位置插入100,位置用迭代器表示
vars.insert(vars.begin(), 2, 100);
// 插入多个相同的元素,此处插入2个100
vector<int> cop = {6,7,8};
vars.insert(vars.end(), cop.begin(), cop.end());
// 也可以进行vector之间的拼接
6.删除元素
pop_back()删除最后一个元素。
erase() 删除指定位置元素.(其中的参数要是指针变量,比如begain(),end(),以及迭代器值) 例如vec.erase(vec.begin()+2);删除第3个元素
clear() 清除所有元素。
empty() )判断该数组是否为空
vector<int> vars = {1,2,3,4,5,6};
vars.pop_back();
// 弹出最后一个元素,注意只是弹出,不返回其值,用vector.back()返回其值
vars.clear(); // 清空vector
auto iter = vars.erase(vars.begin()+1);
// 删除单个元素,指定迭代器,删除后vector的大小减1,但是容量不变。
// 其返回一个迭代器,指向被删除元素后的第一个元素。
删除从一个位置到另一个位置
auto iter = vars.erase(vars.begin(), vars.begin()+2); // 删除一个范围内的值,指定开头,结尾的迭代器即可。
7.排序和翻转
#include<algorithm>
//采用的是从小到大的排序
sort(vec.begin(),vec.end());
// 将元素翻转,即逆序排列
reverse(vec.begin(),vec.end());
8.底层原理
底层原理:动态数组
动态增长的数组,里面有一个指针指向一片连续的内存空间,当空间装不下要容纳的数据的时候会自动申请一片更大的空间(空间配置器)将原来的数据拷贝到新的空间,然后就会释放旧的空间。当释放或者删除(vec.clear())的数据时候并不会释放只是清空了里面的数据。
vector中有三个迭代器first,last,end, 分别指向了数组的开头, 数组的结尾+1以及数组的最大容量结尾,迭代器这里可以理解为是指针
int first,last,end;
unsigned int size(){
//通过首尾 很容易得出size
return last-first;
}
bool empty(){
//可以直接判断是否为空
return last==first;
}
unsigned int capacity(){
//得到当前数组的容量
return end-begin;
}
vector 容器扩容:
- 完全弃用现有的内存空间,重新申请更大的内存空间;
- 将旧内存空间中的数据,按原有顺序移动到新的内存空间中;
- 最后将旧的内存空间释放。
扩容的倍数关系:在VS中, 该倍数为1.5 而在GCC中, 该倍数为2
reserve是直接扩充到已经确定的大小,可以减少多次开辟、释放空间的问题
resize()可以改变有效空间的大小,也有改变默认值的功能。capacity的大小也会随着改变。resize()可以有多个参数。
9.特殊记忆
互换容器
v1.swap(v2);//将v2的元素与v1元素互换
# 针对二维vector的处理
/ 第一维度从小到大, (第一维度相同时,按第二维度从大到下)
sort(envelopes.begin(),envelopes.end(),[](const auto&a,const auto&b){
if(a[0]!=b[0]){
return a[0]<b[0];
}else{return a[1]>b[1];}
});
函数总结
函数成员 | 函数功能 | |
---|---|---|
成员函数 | operator[ ] | 重载了 [ ] 运算符,可以向访问数组中元素那样,通过下标即可访问甚至修改 vector 容器中的元素。 |
成员函数 | assign() | 用新元素替换原有内容。 |
容量 | size() | 返回实际元素个数。 |
容量 | max_size() | 返回元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。 |
容量 | empty() | 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 |
容量 | capacity() | 返回当前容量。 |
元素访问 | at() | 使用经过边界检查的索引访问元素。 |
元素访问 | front() | 返回第一个元素的引用。 |
元素访问 | back() | 返回最后一个元素的引用。 |
元素访问 | data() | 返回指向容器中第一个元素的指针。 |
修改器 | resize() | 改变实际元素的个数。 |
修改器 | reserve() | 增加容器的容量。 |
修改器 | push_back() | 在序列的尾部添加一个元素。 |
修改器 | pop_back() | 移出序列尾部的元素。 |
修改器 | insert() | 在指定的位置插入一个或多个元素。 |
修改器 | erase() | 移出一个元素或一段元素。 |
修改器 | clear() | 移出所有的元素,容器大小变为 0。 |
修改器 | swap() | 交换两个容器的所有元素。 |
迭代器 | begin() | 返回指向容器中第一个元素的迭代器。 |
迭代器 | end() | 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用。 |
迭代器 | rbegin() | 返回指向最后一个元素的迭代器。 |
迭代器 | rend() | 返回指向第一个元素所在位置前一个位置的迭代器。 |
迭代器 | cbegin() | 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
迭代器 | cend() | 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
迭代器 | crbegin() | 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
迭代器 | crend() | 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
emplace() | 在指定的位置直接生成一个元素。 | |
emplace_back() | 在序列尾部生成一个元素。 |
参考资料
https://www.w3schools.cn/cpp_standard_library/vector.html
https://www.apiref.com/cpp-zh/cpp/container/vector.html