STL (Standard Template Library):是 C++ 标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
通俗来说:STL 就是将常见的数据结构(例如 顺序表,链表,栈,队列,二叉树,哈希...)以模板的形式进行封装,使用时,不用我们人为再去写,可以直接调用。并且包含常见的通用的泛型算法(一些常规的算法也不用自己实现,可以直接调用)。
STL 六大组件
-
容器(Container): 各种数据结构,如 vector、list、deque、set、map 等,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器。
-
算法(Algorithm): 各种常用算法,提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作,如 sort、find、copy、erase 函数等。函数本身与它们操作的数据的结构和类型无关,因此它们可以在从简单数组到高度复杂容器的任何数据结构上使用。
-
迭代器(Iterator): 迭代器提供了访问容器中对象的方法,扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共有 5 种类型,以及其他衍生变化,是一种将 operator*、operator->、operator++、operator-- 等指针操作予以重载的模板类。所有的 STL 容器附带有自己专属的迭代器,因为只有容器设计者才知道如何遍历自己的元素。
c++11版本及以后就可以不用迭代器了。
-
仿函数(Functor): 也称为函数对象(Function object),行为类似函数,可作为算法的某种策略。从实现角度来看,仿函数是一种重载了 operator() 的类或者模板类。
-
适配器(Adaptor): 一种用来修饰容器、仿函数或者迭代器接口的机制。例如 STL 提供的 queue 和 stack,就是一种空间配接器,因为它们的底部完全借助于 deque。
-
分配器(allocator): 也称为空间配置器,负责空间的配置与管理。从实现的角度来看,配置器是一个实现了动态配置空间、空间管理、空间释放的模板类。
算法 (Algorithm)
头文件:`#include
`
### 常用函数
- **`sort()`**
- **功能:** `sort()` 函数可以对给定区间所有元素进行排序。
- **参数:** `sort(begin, end, cmp)`
- `begin`:指向待 `sort()` 的数组的第一个元素的指针。
- `end`:指向待 `sort()` 的数组的最后一个元素的下一个位置的指针。
- `cmp`:排序准则,可以不写,默认从小到大进行排序。
```c++
#include
#include
using namespace std;
int main(){
int num[10] = {6,5,9,1,2,8,7,3,4,0};
// greater
() 是一个仿函数,表示降序排列,这里只做演示,是一个伪代码
sort(num, num+10, greater
());
// 排序后 num 变为:9 8 7 6 5 4 3 2 1 0
return 0;
}
```
- **`swap()`**交换两个数的值
```c++
int a = 1, b = 2 ;
cout << a << ' ' << b << '\n' ;
swap(a, b) ;
```
- **`min()`**取最小值
- **`max()`**取最大值
### 💡 排序练习
[P5740 【深基7.例9】最厉害的学生 - 洛谷](https://www.luogu.com.cn/problem/P5740)
# P5740 【深基7.例9】最厉害的学生
## 题目描述
现有 $N$ 名同学参加了期末考试,并且获得了每名同学的信息:姓名(不超过 $8$ 个字符的仅有英文小写字母的字符串)、语文、数学、英语成绩(均为不超过 $150$ 的自然数)。总分最高的学生就是最厉害的,请输出最厉害的学生各项信息(姓名、各科成绩)。如果有多个总分相同的学生,输出靠前的那位。
## 输入格式
第一行输入一个正整数 $N$,表示学生个数。
第二行开始,往下 $N$ 行,对于每一行首先先输入一个字符串表示学生姓名,再输入三个自然数表示语文、数学、英语的成绩。均用空格相隔。
## 输出格式
输出最厉害的学生。
## 输入输出样例 #1
### 输入 #1
```
3
senpai 114 51 4
lxl 114 10 23
fafa 51 42 60
```
### 输出 #1
```
senpai 114 51 4
```
## 说明/提示
数据保证,$1 \leq N \leq 1000$,姓名为长度不超过 $8$ 的字符串,语文、数学、英语成绩均为不超过 $150$ 的自然数。
---
**自定义 `cmp` 函数实现结构体排序**
```c++
#include
using namespace std ;
const int N = 1008 ;
struct node {
string name ;
int a, b, c ;
int sum ;
int num ;
} no[N];
// 自定义比较函数
bool cmp(node x, node y) {
// 如果总分相同
if (x.sum == y.sum) {
// 按学号从小到大
return x.num < y.num ;
}
// 否则按总分从大到小
return x.sum > y.sum ;
}
int main() {
int n ;
cin >> n ;
for (int i = 1 ; i <= n ; i ++) {
cin >> no[i].name >> no[i].a >> no[i].b >> no[i].c ;
no[i].sum = no[i].a + no[i].b + no[i].c ;
no[i].num = i ;
}
// 使用自定义的 cmp 函数进行排序
sort(no + 1, no + n + 1, cmp) ;
cout << no[1].name << ' ' << no[1].a << ' ' << no[1].b << ' ' << no[1].c <<'\n' ;
return 0 ;
}
```
------
## 📦 容器 (Container)
容器是存放数据的数据结构,比如链表,数组,队列... 容器都是一个类(用法与结构体相似)。访问类对象内的函数或变量用点运算符 `.`。
### `vector` (可变长度数组)
vector翻译为向量,但是这里使用“变长数组”的叫法更容易理解,也即“长度根据需要而自动改变的数组”。我们知道在C语言中,普通数组大小一旦确定就不能改变了,在做题时有时会碰到只用普通数组会超内存的情况,这时我们就可以使用vector来定义不定长数组节省空间。
#### 定义
```c++
#include
vector
name;
// 示例:
vector
v = {1, 2, 3};
```
#### 常用函数
- `push_back(x)`:在 vector 后面添加一个元素 `x`,时间复杂度 O(1)。
- `pop_back()`:删除 vector 最后一个元素,时间复杂度 O(1)。
- `back()`:返回最后一个元素的值。
- `front()`:返回第一个元素的值。
- `size()`:返回 vector 中元素的个数,时间复杂度 O(1)。
- `clear()`:清空 vector 中的所有元素,时间复杂度 O(N)。
- `insert(it, x)`:向迭代器 `it` 处插入一个元素 `x`,时间复杂度 O(N)。
- `erase(it)`:删除迭代器 `it` 处的元素。
- `erase(first, last)`:删除 `[first, last)` 区间内的所有元素。
#### 迭代器
```c++
vector
v = {1, 2, 3};
vector
::iterator it ;
// 传统迭代器遍历
for (it = v.begin() ; it != v.end() ; it ++) {
cout << *it << '\n' ;
}
// C++11
//
//
//
for (auto i : v) { // auto 自动推导类型
cout << i << ' ' ;
}
```
#### 练习
[P1567 统计天数 - 洛谷](https://www.luogu.com.cn/problem/P1567)
# P1567 统计天数
## 题目描述
炎热的夏日,KC 非常的不爽。他宁可忍受北极的寒冷,也不愿忍受厦门的夏天。最近,他开始研究天气的变化。他希望用研究的结果预测未来的天气。
经历千辛万苦,他收集了连续 $N(1 \leq N \leq 10^6)$ 天的最高气温数据。
现在,他想知道最高气温一直上升的最长连续天数。
## 输入格式
第 1 行:一个整数 $N$ 。$1 \leq N \leq 10^6$
第 2 行:$N$个空格隔开的整数,表示连续 $N$ 天的最高气温。$0 \leq$ 最高气温 $\leq 10^9$ 。
## 输出格式
1 行:一个整数,表示最高气温一直上升的最长连续天数。
## 输入输出样例 #1
### 输入 #1
```
10
1 2 3 2 4 5 6 8 5 9
```
### 输出 #1
```
5
```
---
```c++
#include
using namespace std ;
int main() {
int n ;
cin >> n ;
vector
a;
for (int i = 1 ; i <= n ; i ++) {
int x ;
cin >> x ;
a.push_back(x) ;
}
int ans = 1, tmp = 1 ;
for (int i = 1 ; i < a.size() ; i ++) {
if (a[i] > a[i - 1]) {
tmp ++ ;
} else {
ans = max(ans, tmp) ;
tmp = 1 ;
}
}
ans = max(ans, tmp) ; // 别忘了最后一次的比较
cout << ans << '\n' ;
return 0 ;
}
```
------
### `string` (字符串)
C++ 在 STL 中加入了 `string` 类型,对字符串常用的需求功能进行了封装,使得操作起来更方便,且不易出错。
#### 头文件
```c++
#include
```
#### 定义
```c++
string a = "abcd";
```
#### 常用函数
- `+=`:字符串拼接,假设有两个字符串`a`和`b`,可用`a+=b`或`a=a+b`来将`b`接到`a`的后面。
- `==`, `!=`, `<`, `<=`, `>`, `>=`:按字典序比较大小。
- `length()` / `size()`:返回字符串长度,O(1)。
- `erase(it)`:删除 `it` 处的字符,`it` 为迭代器。
- `erase(first, last)`:删除 `[first, last)` 区间的字符,`first`, `last` 为迭代器。
- `erase(pos, length)`:`pos` 为开始删除的起始位置,`length` 为删除的字符个数。
- `clear()`:清空字符串 O(1)。
- `substr(pos, len)`:返回从 `pos` 号位置开始、长度为 `len` 的子串,O(len)。
- `find(str2)`:当 `str2` 是 `str` 的子串时,返回其在 `str` 中第一次出现的位置;否则返回 `string::npos`。O(NM)。
- `front()`:返回第一个字符。
- `back()`:返回最后一个字符。
- `push_back(x)`:将字符 `x` 加到字符串后。
- `pop_back()`:删除最后一个字符。
------
### `map` (映射)
Map (映射) 元素包含两部分(key, value),key 和 value 可以是任意类型。在 map 里面,一个 key 对应一个 value,类似函数里一个 x 对应一个 y。并且在 map 里,key 不能重复,自动按 key 从小到大排序。
#### 定义
```c++
#include
Comments NOTHING