STL
一、定义
1、STL = Standard Template Library.
标准模板库,即为现成的算法,数据结构模板;
2、大致分类:
containercontainercontainer(容器):
包含、放置数据的地方;
iteratoriteratoriterator(迭代器):
在容器中指出一个位置,或成对使用以划定一个区域,用来限定操作系统涉及到的数据范围;
algorithmalgorithmalgorithm(算法):
要执行的操作;
二、栈
1、定义
栈是一种特殊线性表,其插入和删除的操作都限制在表的一端进行,这一端被称作“栈顶(top)”,另一端称作“栈底(bottom)”。插入操作称为“进栈(push)”或者“压栈”,删除操作被称为“出栈(pop)”。栈的特点是“先进后出(FILO,First in last out)”。

2、基本操作
头文件:
#include <stack>
初始化:
stack<数据类型> 栈名;
判空
栈名.empty() //返回值为真,表示栈空,为假不空
求栈中元素的个数
栈名.size()//返回栈大小
进栈(压栈)
栈名.push(进栈元素)
出栈
栈名.pop()
取栈顶元素
栈名.top()//返回值为栈顶元素值
三、队列
队列
1、定义
队列是一种特殊线性表。其插入操作限定在表的一端进行,称为“入队”;其删除操作则限定在表的另一端进行,称为“出队”。插入一端称为队尾(rear);删除一端称为队头(front)。队列也被称作“先进先出”线性表(FIFO, first inFirst out)。在入队、出队的过程中,队列将会呈现出以下几种状态:
队空:队列中没有任何元素。
队满:队列空间已全被占用。
溢出:当队列已满,却还有元素要入队,就会出现“上溢(overflow)”;当队列已空,却还要做“出队”操作,就会出现“下溢( underflow)”。两种情况合在一起称为队列的“溢出”。

2、基本操作
头文件:
#include<queue>
初始化:
queue <数据类型> 队列名;
判空:
队列名.empty()//返回值是空,为假时非空
求队列中实际元素的个数:
队列名.size()
入队:
队列名.push(x)
出队:
队列名.pop()
取队首元素:
队列名.front()
取队尾元素:
队列名.back()
优先队列
1、定义
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。即优先队列就为可在插入数后进行自动排序的队列。
2、定义
头文件:
#include <queue>
#include <vector>
定义:
priority_queue <int, vector<int>, greater<int> > q;//定义q为整形升序队列;
priority_queue <int, vector<int> > q;//定义q为整形降序队列;
判空:
队列名.empty()//返回值是空,为假时非空
求队列中实际元素的个数:
队列名.size()
入队:
队列名.push(x)
出队:
队列名.pop()
取队首元素 :
队列名.front()
取队尾元素:
队列名.back()
Deque
1、定义
deque 是 double-ended queue 的缩写,又称双端队列容器。deque 容器和 vecotr 容器有很多相似之处,比如:
deque 容器也擅长在序列尾部添加或删除元素(时间复杂度为O(1)),而不擅长在序列中间添加或删除元素。
deque 容器也可以根据需要修改自身的容量和大小。
和 vector 不同的是,deque 还擅长在序列头部添加或删除元素,所耗费的时间复杂度也为常数阶O(1)。
当需要向序列两端频繁的添加或删除元素时,应首选 deque 容器。
2、创建格式
头文件:
#include <deque>
创建方式:
定义空容器:
deque < 数据类型 > 容器名;
例子:
deque <int> a;
定义指定元素容器:
deque < 数据类型 > 容器名 { 从0开始下标的数字值 };
例子:
deque < int > a { 2, 3, 4, 5, 10 };
定义指定长度的容器:
deque < 数据类型 > 容器名 ( 初始值为0,下标从0开始的元素个数 )
例子:
deque < int > a(20);
3、常用函数
判空
队列名.empty()//返回值是空,为假时非空
求队列中实际元素的个数
队列名.size()
在首段插入x元素值
队列名.push_front(x)
在尾端插入x元素值
队列名.push_back(x)
删除首段元素
队列名.pop_front()
删除尾端元素
队列名.pop_back()
取队首元素
队列名.front()
取队尾元素
队列名.back()
清除队列
队列名.claer()
修改大小
队列名.resize(n) //将其大小修改为n
四、Vector容器
1、定义
vector 容器是 STL 中最常用的容器之一,都可以看做是对 C++ 普通数组的“升级版”。不同之处在于,普通数组实现的是静态数组(容量固定的数组),而 vector 实现的是动态数组,即可以进行元素的插入和删除,在此过程中,vector 会动态调整所占用的内存空间。vector 常被称为向量容器,因为该容器擅长在尾部插入或删除元素,在常量时间内就可以完成,时间复杂度为O(1);而对于在容器头部或者中部插入或删除元素,则花费时间要长一些(移动元素需要耗费时间),时间复杂度为线性阶O(n)。
2、创建方式
头文件:
#include <vector>
创建格式:
定义空容器:
vector < 数据类型 > 容器名;
例子:
vector < int > a; //定义空容器
定义指定元素容器:
vector < 数据类型 > 容器名 { 初始值 };
例子:
vector < int > a { 2, 3, 4, 5, 6, 7, 8, 9 }; //从下标为0开始赋值;
定义指定长度容量:
vector < 数据类型 > 容器名(下表从0起元素个数)
例子:
vector < int > a(20) //20个元素
创建 vector 时,"< >" 中可以是任何数据类型,可以是基本类型,也可以是已声明的结构体,还可以是容器等,如:
vector < pair <int, string > > a;
3、常用函数
| 函数成员 | 函数功能 |
|---|---|
| 容器名[i] | 访问下标为i的元素(下标从0开始) |
| 容器名.begin() | 返回指向容器中第一个元素的迭代器。 |
| 容器名.end() | 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用。 |
| 容器名.rbegin() | 返回指向最后一个元素的迭代器。 |
| 容器名.rend() | 返回指向第一个元素所在位置前一个位置的迭代器。 |
| 容器名.size() | 返回实际元素个数。 |
| 容器名.resize() | 改变实际元素的个数。 |
| 容器名.capacity() | 返回当前容量。 |
| 容器名.empty() | 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 |
| 容器名.reserve() | 增加容器的容量。 |
| 容器名.shrink_to_fit() | 将内存减少到等于当前元素实际所使用的大小。 |
| 容器名.front() | 返回第一个元素的引用。 |
| 容器名.back() | 返回最后一个元素的引用。 |
| 容器名.data() | 返回指向容器中第一个元素的指针。 |
| 容器名.assign() | 用新元素替换原有内容。 |
| 容器名.push_back() | 在序列的尾部添加一个元素。 |
| 容器名.pop_back() | 移出序列尾部的元素。 |
| 容器名.insert() | 在指定的位置插入一个或多个元素。 |
| 容器名.erase() | 移出一个元素或一段元素。 |
| 容器名.clear() | 移出所有的元素,容器大小变为 0。 |
| 容器名.swap() | 交换两个容器的所有元素。 |
| 容器名.emplace() | 在指定的位置直接生成一个元素。 |
| 容器名.emplace_back() | 在序列尾部生成一个元素。 |
五、迭代器
1、定义
迭代器(iterator)(iterator)(iterator)是STL的重要概念
迭代器是指向 STL 容器内元素的指针,它能够通过自增 (++) 与 (–) 遍历 STL 容器中的所有元素。
STL 在绝大多数容器中需要提供 begin() 和 end() 两个迭代器只向容器中元素的边界。
注意:end() 迭代器指向最后一个元素的下一个位置
2、用法
用输出 vector 数组的所有元素举例:
#include <cstdio>
#include <vector>
using namespace std;
int n;
vector < int > a;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
a.push_back(x);
}
for (vector < int >::iterator i = a.begin(); i < a.end(); i++) {
printf("%d ", *i);
}
}
六、Pair
1、定义
Pair 二元组模板,其专门用来将 2 个普通元素 first 和 second (可以是 c++ 基本数据类型、结构体等) 创建成一个新元素 <first, second>。 使用 pair 类模板来创建“键值对”形式的元素。
2、创建方式
头文件:
#include <uiltliy>
创建格式:
定义空容器:
pair < 键数据类型, 键数据类型 > 容器名;
例子:
pair < int, char > a;
定义指定元素容器;
pair < 键数据类型, 键数据类型 > 容器名( 第一键值, 第二键值 );
例子:
pair < int, char > a(5, 'a');
3、常用函数
赋值:
容器名.first = 1; //第一个键值为1
容器名.second = 2;//第二个键值为2
配对:
将 a 与 b 做成 pair:
make_pair(a, b);
七、Tuple
1、定义
Tuple 为元组容器,它与 pair 的区别为其能够存储多个数值,可用与函数返回多个元素;
2、创建方式
头文件:
#include <tuple>
创建格式:
定义空容器:
tuple <数据类型1, 数据类型2, ...... , 数据类型n> 容器名;
例子:
tuple < string, int, int > a;
定义指定元素容器:
tuple <数据类型1, 数据类型2, ...... , 数据类型n> 容器名 { 数据1, 数据2, ......, 数据n };
例子:
tuple < string, int, int > a{"IOI", 97, 88}
3、基本操作
初始化:
使用 make_tuple() 初始化
访问元素:
访问元素使用"get < 位置 > (容器名)"方法,注意get里面的位置信息,必须是常量表达式;
八、Map
1、定义
map 容器存储的都是 pair 对象, 也就是用 pair 类模板创建的键值对,其中,各个键值对的键和值可以是任意数据类型,包括 基本数据类型,使用结构体或类自定义的类型。 各个键值对中,键的值既不能重复也不能被修改.使用 map 容器存储多个键值对时,该容器会自动根据各键值对的键的大小,按照既定的规则进行排序。默认情况下,map 容器使用 less 排序规则(其中 T 表示键的数据类型),其会根据键的大小对所有键值对做升序排序,也可以自定义排序规则。
2、创建格式
头文件:
#include <map>
创建方式:
定义空容器:
map < 键数据类型, 值数据类型 > 容器名;
例子:
map < string, int > a;
定义指定元素容器:
map < 键数据类型, 值数据类型 > 容器名 { { 第一组键数据, 第一组值数据 }, { 第二组键数据, 第二组值数据 }, ... , { 第n组键数据, 第n组值数据 } }
例子:
map < string, int > a { {"c1", 100}, {"c2", 99} }
3、常用函数
| 函数成员 | 函数功能 |
|---|---|
| 容器名[key] | 返回键为key的值 |
| 容器名[key] = n | 插入键为key,值为n的值 |
| 容器名.begin() | 返回指向容器排好序的第一个元素键值对的双向迭代器。 |
| 容器名.end() | 返回指向容器排好序的最后一个元素所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。 |
| 容器名.rbegin() | 返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。 |
| 容器名.rend() | 返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。 |
| 容器名.find(key) | 在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
| 容器名.lower_bound(key) | 返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
| 容器名.upper_bound(key) | 返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
| 容器名.empty() | 若容器为空,则返回 true;否则 false。 |
| 容器名.size() | 返回当前 map 容器中存有键值对的个数。 |
| 容器名.insert() | 向 map 容器中插入键值对。 |
| 容器名.erase() | 删除 map 容器指定位置、指定键(key)值或者指定区域内的键值对。后续章节还会对该方法做重点讲解。 |
| 容器名.swap() | 交换 2 个 map 容器中存储的键值对,这意味着,操作的 2 个键值对的类型必须相同。 |
| 容器名.clear() | 清空 map 容器中所有的键值对,即使 map 容器的 size() 为 0。 |
| 容器名.emplace() | 在当前 map 容器中的指定位置处构造新键值对。其效果和插入键值对一样,但效率更高。 |
| 容器名.count(key) | 在当前 map 容器中,查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1。 |
九、Multimap
1、定义
Multimap 容器具有和 Map 相同的特性,即 Multimap 容器也用于存储 pair <const K, T> 类型的键值对(其中 K 表示键的类型, T表示值的类型,其中各个键值对的键的值不能做修改:且,该容器也会自行根据键的大小对存储的所有键值对做排序操作。和 map 容器的区别在于,multimap 容器中可以同时存储多(≥2)个键相同的键值对。
2、创建格式
头文件:
#include <map>
创建方式:
定义空容器:
multimap < 键数据类型, 值数据类型 > 容器名;
例子:
multimap < string, int > a;
定义指定元素容器:
multimap < 键数据类型, 值数据类型 > 容器名 { { 第一组键数据类型值, 第一组值数据类型值 }, { 第一组键数据类型值, 第一组值数据类型值 } };
例子:
multimap < string, int > a { {"c1", 100}, {"c2", 99} };
3、常用函数
函数与map函数一致;
十、Set
1、定义
和 map、multimap 容器不同,使用 set 容器存储的各个键值对,要求键 key 和值 value 必须相等。基于 set 容器的这种特性,当使用 set 容器存储键值对时,只需要为其提供各键值对中的 value 值(也就是 key 的值)即可。使用 set 容器存储的各个元素的值必须各不相同。正常情况下,是无法修改 set 容器中元素的值的,修改 set 容器中元素值的做法是:先删除该元素,然后再添加一个修改后的元素。set 容器也会将元素进行排序,但其中各键值对的键 key 和值 value 是相等的,根据 key 排序,也就等价为根据 value 排序。
2、创建格式
头文件:
#include <set>
创建方式:
定义空容器:
set < 键值数据类型 > 容器名;
例子:
set < int > a;
定义指定元素的容器:
set < 键值数据类型 > 容器名 { 键值数值 };
例子:
set <string> {"IOI", "NOI", "CSP"};
3、常用函数
| 函数成员 | 函数功能 |
|---|---|
| 容器名.begin() | 返回指向排好序的容器的第一个元素的双向迭代器。 |
| 容器名.end() | 返回指向排好序的容器最后一个所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。 |
| 容器名.find(n) | 在 set 容器中查找值为 n 的元素,如果成功找到,则返回指向该元素的双向迭代器;反之,则返回和 end() 方法一样的迭代器。 |
| 容器名.lower_bound(n) | 返回一个指向当前 set 容器中第一个大于或等于 n 的元素的双向迭代器。 |
| 容器名.upper_bound(n) | 返回一个指向当前 set 容器中第一个大于 n 的元素的迭代器。 |
| 容器名.empty() | 若容器为空,则返回 true;否则 false。 |
| 容器名.size() | 返回当前 set 容器中存有元素的个数。 |
| 容器名.insert() | 向 set 容器中插入元素。 |
| 容器名.erase() | 删除 set 容器中存储的元素。 |
| 容器名.swap() | 交换 2 个 set 容器中存储的所有元素。这意味着,操作的 2 个 set 容器的类型必须相同。 |
| 容器名.clear() | 清空 set 容器中所有的元素,即令 set 容器的 size() 为 0。 |
| 容器名.emplace() | 在当前 set 容器中的指定位置直接构造新元素。其效果和 insert() 一样,但效率更高。 |
| 容器名.count(n) | 在当前 set 容器中,查找值为 n 的元素的个数,并返回。注意,由于 set 容器中各元素的值是唯一的,因此该函数的返回值最大为 1。 |
十一、List
1、定义
list 容器,又称双向链表容器,这意味着,list 容器中的元素可以分散存储在内存空间里。list 容器中各个元素的前后顺序是靠指针来维系的,每个元素都配备了 2 个指针,分别指向它的前一个元素和后一个元素。其中第一个元素的前向指针总为 null,因为它前面没有元素;同样,尾部元素的后向指针也总为 null。基于这样的存储结构,list 容器具有可以在序列已知的任何位置快速插入或删除元素(时间复杂度为O(1))。并且在 list 容器中移动元素,也比其它容器的效率高。
2、创建格式
头文件:
#include <list>
创建方式:
定义空容器:
list < 数据类型 > 容器名;
例子:
list < int > a; //定义空容器
定义指定元素容器:
list < 数据类型 > 容器名 { 初始值 };
例子:
< int > a { 2, 3, 4, 5, 6, 7, 8, 9 }; //从下标为0开始赋值;
定义指定长度容量:
list < 数据类型 > 容器名(下表从0起元素个数)
例子:
list < int > a(20) //20个元素
3、常用函数
| 函数成员 | 函数功能 |
|---|---|
| 容器名.begin() | 返回指向容器中第一个元素的双向迭代器。 |
| 容器名.end() | 返回指向容器中最后一个元素所在位置的下一个位置的双向迭代器。 |
| 容器名.empty() | 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 |
| 容器名.size() | 返回当前容器实际包含的元素个数。 |
| 容器名.front() | 返回第一个元素的引用。 |
| 容器名.back() | 返回最后一个元素的引用。 |
| 容器名.assign() | 用新元素替换容器中原有内容。 |
| 容器名.push_front() | 在容器头部插入一个元素。 |
| 容器名.pop_front() | 删除容器头部的一个元素。 |
| 容器名.push_back() | 在容器尾部插入一个元素。 |
| 容器名.pop_back() | 删除容器尾部的一个元素。 |
| 容器名.insert() | 在容器中的指定位置插入元素。 |
| 容器名.erase() | 删除容器中一个或某区域内的元素。 |
| 容器名.swap() | 交换两个容器中的元素,必须保证这两个容器中存储的元素类型是相同的。 |
| 容器名.resize() | 调整容器的大小。 |
| 容器名.clear() | 删除容器存储的所有元素。 |
| 容器名.splice() | 将一个 list 容器中的元素插入到另一个容器的指定位置。 |
| 容器名.remove(n) | 删除容器中所有等于 n 的元素。 |
| 容器名.remove_if() | 删除容器中满足条件的元素。 |
| 容器名.unique() | 删除容器中相邻的重复元素,只保留一个。 |
| 容器名.merge() | 合并两个事先已排好序的 list 容器,并且合并之后的 list 容器依然是有序的。 |
| 容器名.sort() | 通过更改容器中元素的位置,将它们进行排序。 |
| 容器名.reverse() | 反转容器中元素的顺序。 |
十二、Bitset
1、定义
有些程序要处理二进制的有序集,它的每一个元素只能是0或1,每个元素仅用1 bit 空间。
位标准库提供 bitget 类使得处理位集和更容易;
2、创建格式
头文件
#include <bitset>
创建方式
空容器:
bitset < 长度 > 容器名;
副本:
bitset < n > b(u); //b是unsigned long long型的u副本;
bitset < n > b(s); //b是string对象s中含有的位串的副本
bitset < n > b(s, pos, n); //b是s中从位置pos开始的n各位的副本
3、常用函数
| 函数成员 | 函数功能 |
|---|---|
| 容器名[x] | 访问容器名中x位置的元素 |
| 容器名.count() | 求容器名中1的数量 |
| 容器名.size() | 返回元素的个数(包含前导0) |
| 容器名.test(x) | 检查x位是1还是0,是1返回true,0返回false |
| 容器名.flip() | 所有为按位取反 |
十三、常用函数
排序:
1:将区间 [beg, end) 升序排序:
sort(beg, end);
2:对数组元素a[1]~a[n]排序:
sort(1 + a, 1 + a + n);
3:自定义比较函数:
sort(1 + a, 1 + a + n, cmp);
4:对vector数组排序:
sort(a.begin(), a.end());
5:稳定的排序:
stable_sort(beg, end, cmp);
其在两个数相等的时候不会交换位置;
查找:
1:二分查找升序序列 [beg, end) 中第一个大于等与x的位置,返回指针,找不到返回end;
lower_bound(beg, end, x);
2:二分查找升序序列 [beg, end) 中第一个大于x的位置,返回指针,找不到返回end;
upper_bound(beg, end, x);
去重:
将 [beg, end) 中连续多个相同的元素变为一个;
若 [beg, end) 是升序的就能去重,返回去重后的end。
unique(beg, end);
比较:
1:最大值
max(a, b);
2:最小值
min(a, b);
随机:
将区间 [beg, end) 随机打乱
random_shuffle(beg, end);
590

被折叠的 条评论
为什么被折叠?



