会员登录|免费注册|忘记密码|管理入口 返回主站||保存桌面
【0基础stl快速入门】算竞常用stl用法
2024-12-14IP属地 湖北1

C++ 标准模板库 (STL, Standard Template Library)

【0基础stl快速入门】算竞常用stl用法

 
 
 

2.2.1 常用方法

构造

.

 
尾接 & 尾删
  • :在 vector 尾接一个元素,数组长度 .
  • :删除 vector 尾部的一个元素,数组长度
 
清空

清空 vector

判空

如果是空返回 反之返回 .

时间复杂度

改变长度

修改 vector 的长度

  • 如果是缩短,则删除多余的值
  • 如果是扩大,且指定了默认值,则新元素均为默认值**(旧元素不变)**

时间复杂度

2.2.2 适用情形

一般情况 可以替换掉普通数组,除非该题卡常。

有些情况普通数组没法解决: 的矩阵, 且

  • 如果用普通数组 ,浪费内存,会导致 MLE。
  • 如果使用 ,完美解决该问题。

另外, 的数据储存在堆空间中,不会爆栈。

2.2.3 注意事项

提前指定长度

如果长度已经确定,那么应当直接在构造函数指定长度,而不是一个一个 . 因为 额外内存耗尽后的重分配是有时间开销的,直接指定长度就不会出现重分配了。

当心 size_t 溢出

vector 获取长度的方法 返回值类型为 ,通常 OJ 平台使用的是 32 位编译器(有些平台例如 cf 可选 64 位,那么该类型范围为 .

 
 

通过二次封装双端队列 (deque) 容器,实现先进后出的栈数据结构。

2.3.1 常用方法

作用用法示例构造进栈出栈取栈顶查看大小 / 清空 / 判空略略

2.3.2 适用情形

如果不卡常的话,就可以直接用它而不需要手写栈了。

另外,vector 也可以当栈用,vector 的 取尾部元素,就相当于取栈顶, 相当于进栈, 相当于出栈。

2.3.3 注意事项

不可访问内部元素!(cout<<)

通过二次封装双端队列 (deque) 容器,实现先进先出的队列数据结构。

2.4.1 常用方法

作用用法示例构造进队出队取队首取队尾查看大小 / 清空 / 判空略略

2.4.2 适用情形

如果不卡常的话,就可以直接用它而不需要手写队列了。

2.4.3 注意事项

不可访问内部元素

提供常数时间的最大元素查找,对数时间的插入与提取,底层原理是二叉堆。

2.5.1 常用方法

构造

  • 类型:要储存的数据类型
  • 容器:储存数据的底层容器,默认为 ,竞赛中保持默认即可
  • 比较器:比较大小使用的比较器,默认为 ,可自定义
 
其他
作用用法示例进堆出堆取堆顶查看大小 / 判空略略

进出队复杂度 ,取堆顶 .

2.5.2 适用情形

持续维护元素的有序性:每次向队列插入大小不定的元素,或者每次从队列里取出大小最小/最大的元素,元素数量 ,插入操作数量 .

  • 每次插入后进行快速排序
  • 使用优先队列维护

2.5.3 注意事项

仅堆顶可读

只可访问堆顶,其他元素都无法读取到。下面是错误用法

 
所有元素不可写

堆中所有元素是不可修改的。下面是错误用法

 

如果你恰好要修改的是堆顶元素,那么是可以完成的

 
 

提供对数时间的插入、删除、查找的集合数据结构。底层原理是红黑树。

集合三要素解释setmultisetunordered_set确定性一个元素要么在集合中,要么不在✔✔✔互异性一个元素仅可以在集合中出现一次✔❌(任意次)✔无序性集合中的元素是没有顺序的❌(从小到大)❌(从小到大)✔

2.6.1 常用方法

构造

  • 类型:要储存的数据类型
  • 比较器:比较大小使用的比较器,默认为 ,可自定义
 
遍历

可使用迭代器进行遍历

 

基于范围的循环(C++ 11

 
其他
作用用法示例插入元素删除元素查找元素判断元素是否存在查看大小 / 清空 / 判空略略

增删查时间复杂度均为

2.6.2 适用情形

  • 元素去重
  • 维护顺序
  • 元素是否出现过:元素大小 ,元素数量 ,vis 数组无法实现,通过 set 可以完成。

2.6.3 注意事项

不存在下标索引

set 虽说可遍历,但仅可使用迭代器进行遍历,它不存在下标这一概念,无法通过下标访问到数据。下面是错误用法

 
元素只读

set 的迭代器取到的元素是只读的(因为是 const 迭代器,不可修改其值。如果要改,需要先 erase 再 insert. 下面是错误用法

 
不可用迭代器计算下标

set 的迭代器不能像 vector 一样相减得到下标。下面是错误用法

 
 

提供对数时间的有序键值对结构。底层原理是红黑树。

映射

性质解释mapmultimapunordered_map互异性一个键仅可以在映射中出现一次✔❌(任意次)✔无序性键是没有顺序的❌(从小到大)❌(从小到大)✔

2.7.1 常用方法

构造

  • 键类型:要储存键的数据类型
  • 值类型:要储存值的数据类型
  • 比较器:键比较大小使用的比较器,默认为 ,可自定义
 

对于需要自定义比较器的情况,涉及一些初学时容易看迷糊的语法(重载小括号运算符 / lambda 表达式,在此就不展开讲了。

遍历

可使用迭代器进行遍历

 

基于范围的循环(C++ 11

 

结构化绑定 + 基于范围的循环(C++17

 
示例
 
 
其他
作用用法示例增 / 改 / 查元素中括号查元素(返回迭代器)删除元素判断元素是否存在查看大小 / 清空 / 判空略略

增删改查时间复杂度均为

2.7.2 适用情形

需要维护映射的场景可以使用:输入若干字符串,统计每种字符串的出现次数。()

2.7.3 注意事项

中括号访问时默认值

如果使用中括号访问 map 时对应的键不存在,那么会新增这个键,并且值为默认值,因此中括号会影响键的存在性。

 
不可用迭代器计算下标

map 的迭代器不能像 vector 一样相减得到下标。下面是错误用法

 
 

顾名思义,就是储存字符串的。

2.8.1 常用方法

构造

构造函数

 
输入输出

C++

 

C

 
其他
作用用法示例修改、查询指定下标字符是否相同字符串连接尾接字符串取子串查找字符串
数值与字符串互转(C++11
源目的函数int / long long / float / double / long doublestringto_string()stringintstoi()stringlong longstoll()stringfloatstof()stringdoublestod()stringlong doublestold()

2.8.3 注意事项

尾接字符串一定要用

string 的 += 运算符,将会在原字符串原地尾接字符串。而 + 了再 = 赋值,会先生成一个临时变量,在复制给 string.

通常字符串长度可以很长,如果使用 + 字符串很容易就 TLE 了。

方法的奇葩参数

一定要注意,C++ string 的取子串的第一个参数是子串起点下标,第二个参数是子串长度

第二个参数不是子串终点!不是子串终点!要与 java 等其他语言区分开来。

方法的复杂度

该方法实现为暴力实现,时间复杂度为 .

顾名思义,就是储存二元组的。

2.9.1 常用方法

构造

  • 第一个值类型:要储存的第一个值的数据类型
  • 第二个值类型:要储存的第二个值的数据类型
 
赋值

老式

 

列表构造 C++11

 
取值

直接取值

  • 取第一个值
  • 取第二个值
排序定义
 
 

结构化绑定 C++17

 
判同

直接用 运算符

 

2.9.2 适用场景

所有需要二元组的场景均可使用,效率和自己定义结构体差不多。

对于一个 vector,我们可以用下标遍历

 

我们同时也可以用迭代器来遍历

 
  • 是一个迭代器,指向的是第一个元素
  • 是一个迭代器,指向的是最后一个元素再后面一位
  • 上述迭代器具有自增运算符,自增则迭代器向下一个元素移动
  • 迭代器与指针相似,如果对它使用解引用运算符,即 ,就能取到对应值了

通过迭代器,我们就能遍历 set 中的元素了

 
 

对于 vector 容器,它的迭代器功能比较完整,以它举例

  • :头迭代器
  • :尾迭代器
  • :反向头迭代器
  • :反向尾迭代器
  • 迭代器 整型:将迭代器向后移动
  • 迭代器 整型:将迭代器向前移动
  • 迭代器 :将迭代器向后移动 1 位
  • 迭代器 :将迭代器向前移动 1 位
  • 迭代器 迭代器:两个迭代器的距离
  • :返回 it 的前一个迭代器
  • :返回 it 的后一个迭代器

对于其他容器,由于其结构特性,上面的功能不一定都有(例如 set 的迭代器是不能相减求距离的

和 指向的位置是无意义的值

对于一个长度为 10 的数组,第 10 位是不可访问的

对于一个长度为 10 的容器,.end 是不可访问的

不同容器的迭代器功能可能不一样

迭代器细化的话有正向、反向、双向,每个容器的迭代器支持的运算符也可能不同,因此不同容器的迭代器细节很有可能是不一样的。

删除操作时需要警惕

建议:如无必要,别用迭代器操作容器。(遍历与访问没关系

已升序排序的元素中,应用二分查找检索指定元素,返回对应元素迭代器位置。找不到则返回尾迭代器。

  • : 寻找 的第一个元素的位置
  • : 寻找 的第一个元素的位置

怎么找 / 的第一个元素呢

  • 的第一个元素的前一个元素(如果有)便是 的第一个元素
  • 的第一个元素的前一个元素(如果有)便是 的第一个元素

返回的是迭代器,如何转成下标索引呢?减去头迭代器即可。

用法示例

 
 

我们通常写成一行

 
 

反转一个可迭代对象的元素顺序

用法示例

 
 

返回最大值 / 最小值的数值

用法示例

 

在 C++11 之后,可以使用列表构造语法传入一个列表,这样就能一次性给多个元素找最大值而不用套娃了

 
 

消除数组的重复相邻元素,数组长度不变,但是有效数据缩短,返回的是有效数据位置的结尾迭代器。

例如,下划线位置为返回的迭代器指向。

 

用法示例

单独使用 unique 并不能达成去重效果,因为它只消除相邻的重复元素。但是如果序列有序,那么它就能去重了。

但是它去重后,序列尾部会产生一些无效数据,为了删掉这些无效数据,我们需要结合 erase.

最终,给 vector 去重的写法便是

 
 

所有函数参数均支持 / / / /

公式示例

注意事项

由于浮点误差,有些的数学函数的行为可能与预期不符,导致 WA。如果你的操作数都是整型,那么用下面的写法会更稳妥。

    • 别用
    • 要用
    • 别用
    • 要用
    • 别用
    • 要用:二分查找
    • 别用
    • 要用:快速幂
    • 别用
    • 要用(不规范,但是这是竞赛)/ (C++20 可用

(C++17)返回最大公因数 / 最小公倍数

 

如果不是 C++17,但是是 GNU 编译器(g++,那么可以用内置函数 .

当然, / 函数也挺好写,直接写也行(欧几里得算法