C++基础笔记5
STL
初步介绍
STL(Standard Template Library),C++标准库的一部分,可以帮助我们处理常见的数据结构和算法。容器是STL的重要组成部分,用于存储和组织数据的对象。
vertor
概念
动态数据容器:相比于数组在一开始就申明了大小,vector无需再申明时确定大小,可以做到动态调整容量,所以称之为动态数组
使用
- 首先引入头文件
#include <vector>
- 定义方法为
vector <类型> 变量名
,例如vector<int> vi
; - 如果申明类似二维数组可写作
vector<vertor<int>> vvi;
含义时外层容器的元素是vector<int>
,内层容器的元素是int
。比二维数组更灵活
取值/索引
支持下标操作符,形如vi[0];同时,vector支持了通过at来访问元素.==区别at在访问时会检查下标是否越界,若越界在进行时会直接报错==
输入和输出
由于vector在申明时内部没有任何数据,所以需要读取数据到某个变量,然后通过push_back将这个变量扔进容器中
1 | for (int i = 0; i < n; i ++){ |
或使用范围循环for (auto& x: arr) cin >> x;
输出时可以通过size获取容器的大小,然后用for循环进行输出;
1 | for(int i = 0; i < vi.size(); i ++){ |
或利用范围循环来遍历整个容器内的元素for (auto& x: vi) cout << x << endl;
初始化
普通vector容器初始化
- 可以像普通数组一样定义大小
vector<int> v0(5);
,使得容器内被5个0填充; - 如果想填充指定值,就在第二个参数上填上初始值
vector<int> v1(5, 1);
- 或者用花括号像数组一样定义初始值
vector<int> v2{1, 2, 3}
- 还可以用另一个vector进行初始化
vector<int> v3(v1);
==如果初始化申明了vector的大小,就不用每次都用push_back挨个将数据丢入容器内,可以使用范围循环,和数组一样方便的进行数据输入==
利用C++的auto自动类型推导,可以更方便的进行多维vector的初始化
1 | vector<int> v0(5); |
多维vector
引用sunny—ll的文章
总结
vector<vector<int>> table(size1, vector<int>(size2, 0));
代码说明:声明一个名为 table 的容器,其元素为 vector的容器。简单来说类似一个int型的二维数组
具体可理解如下
图中,我将外围容器table的初始化参数分成了两部分 A、B
- A: table外围容器的大小
- B: table外围容器的内容,即 size1个vector型的元素。
- B1:内部容器的大小
- B2:内部容器的内容
vector 二维数组的 初始化
直接初始化
首先,要先知道:二维 vector如何获得行数和列数。
1 | vector<vector<int>> a(r, vector<int>(c)); |
用resize来提前构建
1 | vector<vector<int>> new_mat(r);//注意这个r是不可缺少的,规定其有多少行 |
vector 二维数组的 添加与删除
添加一行
1 | //插入一行数组:将in_row数组插入到第2行! |
添加一列
1 | for(int i=0;i<a.size();i++) |
删除一行
1 | a.erase(a.begin() + 2, a.begin() + 3); |
删除一列
1 | //删除a的第二列 |
二维数组的 输入
例如vector<vector<int>> urls(n);
为有n层的二维数据,使用范围循环输入数据
1 | for (auto& url: urls) { |
二维数组的 输出
引用符号 &
例如定义一个二维容器players(2)
用int CurrentPlayer = 0
,并后续用取模操作实现每次切换玩家,存储数据在数组的不同行,使用引用符使得代码更简洁易读 auto &player = players[CurrentPlayer]
,随后对其进行操作
输出
使用范围循环对数组每一行进行求和计算代码ru’xai
1 | for (auto& player: players) { |
例子
1 |
|
vector高级能力
赋值运算&比较运算
可以将一个vector直接赋值给另一个vector
1 | vector<int> v0{1, 2, 3}; |
两个数组比较大小的方法(==字典序比较法==):挨个比较数组的元素,一旦不同,那么拥有较小元素的vector就是更小的,如果全部相同,则说明两个vector相同
vector常用成员函数
front—获取vector的第一个元素
1 | vector<int> v{1, 2, 3}; |
back—获取vector的最后一个元素
1 | vector<int> v{1, 2, 3}; |
size—获取当前的元素个数
1 | vector<int> v{1, 2, 3}; |
empty—判断当前vector是否为空
1 | vector<int> v{1, 2, 3}; |
clear—清空vector数据
1 | vector<int> v{1, 2, 3}; |
push_back—将数据塞入vector末尾
1 | vector<int> v{1, 2, 3}; |
pop_back—将最后一个数据从vector中移除
1 | vector<int> v{1, 2, 3}; |
resize—重新定义vector的大小
1 | vector<int> v{1, 2, 3}; |
如果比原先小则删除末尾的元素;如果比原先大则用0来填充新增的元素,如果有第二个参数,v.resize(5,1);
则改用第二个参数来填充
begin&end
v.begin()
&v.end()
,返回的是vector起始,末尾迭代器
迭代器分别指向的分别是容器始末,通过迭代器可以访问数组的始末
1 | for (vector<int>::iterator iter = v.begin(); iter ++){ |
因此这个for循环的含义是:初始化迭代器指向第一个元素,然后不断指向下个元素,直到等于末尾迭代器,循环结束
迭代器并非元素本身,而是指向元素,所以想要获取迭代器所指向元素的值,需要用*iter
1 | for(auto iter= v.begin();iter != v.end(); iter++){ |
迭代器另一作用,定位位置;例如删除或增加某一个元素需要用迭代器指定位置
erase—删除元素
通过v.begin()
+下标来定位
1 | vector<int> v{1,2,3,4,5}; |
insert—插入元素
1 | vector<int> v{1,2,3}; |
reverse&emplace_back
后续再做阐述