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
2
3
4
5
for (int i = 0; i < n; i ++){
int x;
cin >> x;
vi.push_back(x);
}

或使用范围循环for (auto& x: arr) cin >> x;

输出时可以通过size获取容器的大小,然后用for循环进行输出;

1
2
3
for(int i = 0; i < vi.size(); i ++){
cout << vi[i] << endl;
}

或利用范围循环来遍历整个容器内的元素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初始化同理vector<vector<int>> v4(2, vector<int>(8,3));但由于元素是vector<int>,所以初始化参数也需要相应的改成vector<int>的初始值
  • 利用C++的auto自动类型推导,可以更方便的进行多维vector的初始化

==如果初始化申明了vector的大小,就不用每次都用push_back挨个将数据丢入容器内,可以使用范围循环,和数组一样方便的进行数据输入==

1
2
3
4
vector<int> v0(5);
for (auto& x: v0){
cin >> x;
}

vector高级能力

赋值运算&比较运算

可以将一个vector直接赋值给另一个vector

1
2
3
4
5
vector<int> v0{1, 2, 3};
vector<int> v1;
v1 = v0;
vector<int> v2{1, 2, 4};
v0 < v2;

两个数组比较大小的方法(==字典序比较法==):挨个比较数组的元素,一旦不同,那么拥有较小元素的vector就是更小的,如果全部相同,则说明两个vector相同

vector常用成员函数

front—获取vector的第一个元素

1
2
vector<int> v{1, 2, 3};
cout << v.front() << endl

back—获取vector的最后一个元素

1
2
vector<int> v{1, 2, 3};
cout << v.back() << endl

size—获取当前的元素个数

1
2
vector<int> v{1, 2, 3};
cout << v.size() << endl

empty—判断当前vector是否为空

1
2
vector<int> v{1, 2, 3};
cout << v.empty() << endl

clear—清空vector数据

1
2
vector<int> v{1, 2, 3};
v.clear();

push_back—将数据塞入vector末尾

1
2
vector<int> v{1, 2, 3};
v.push_back(4);

pop_back—将最后一个数据从vector中移除

1
2
vector<int> v{1, 2, 3};
v.pop_back();

resize—重新定义vector的大小

1
2
vector<int> v{1, 2, 3};
v.resize(3);

如果比原先小则删除末尾的元素;如果比原先大则用0来填充新增的元素,如果有第二个参数,v.resize(5,1);则改用第二个参数来填充

begin&end

v.begin()&v.end(),返回的是vector起始,末尾迭代器

迭代器分别指向的分别是容器始末,通过迭代器可以访问数组的始末

1
2
3
4
for (vector<int>::iterator iter = v.begin(); iter ++){
} //vector<int>::iterator是迭代器的类型,也可以用auto来代替
for(auto iter= v.begin();iter != v.end(); iter++){
} //迭代器支持加法,但这并非算术运算,而是让迭代器指向下个元素

image-20241019142429502

因此这个for循环的含义是:初始化迭代器指向第一个元素,然后不断指向下个元素,直到等于末尾迭代器,循环结束

迭代器并非元素本身,而是指向元素,所以想要获取迭代器所指向元素的值,需要用*iter

1
2
3
for(auto iter= v.begin();iter != v.end(); iter++){
*iter;
}

迭代器另一作用,定位位置;例如删除或增加某一个元素需要用迭代器指定位置

erase—删除元素

通过v.begin()+下标来定位

1
2
3
4
vector<int> v{1,2,3,4,5};
v.erase(v.begin());//只有一个参数代表输出指定位置的元素
vector<int> v{1,2,3,4,5};
v.erase(v.begin() + 1, v.beign() + 3);//若两个参数则表示删除某段连续的元素

insert—插入元素

1
2
3
4
5
vector<int> v{1,2,3};
v.insert(v.begin(), 4); //第一个参数值代表插入的位置,后面的参数代表插入的内容
v.insert(v.begin() + 1, {4,5,6});// 可以是普通的值也可以是一段花括号表示的数据
//还可以是另一个容器的范围 例如v1{1,2,3};v2{4,5,6}
v1.insert(v1.end(),v2.begin,v2.end());//将容器放到另一个容器的尾部,得到新容器v1{1,2,3,4,5,6}

reverse&emplace_back

后续再做阐述