STL(Standard Template Library)标准模板库
整理自《算法笔记》
| vector(向量)
-
头文件
#include<vector>
-
用途:
**1、**变长数组;
**2、**以邻接表存储图(《算法笔记》10.2.2);
3、有些场合需要把部分数据输出在同一行,数据中间用空格隔开,由于输出数据的个数是不确定的,为了更方便地处理最后一个满足条件的数据后面不输出额外的空格,可以先用vector
记录所有需要输出的数据,然后一次性输出。 -
访问:
1、通过下标(从0
到size() - 1
)
2、通过迭代器 (vector<typename>::iterator
)
注:v[i]
与 *(v.begin() + i)
是等价的
- 比较:
vector<>可以直接比较大小,按字典序排列;故vector
数组在用sort()
时无需额外写比较函数;(参考)
只有
string
和vector
中允许使用v.begin()+i
这种迭代器加整数的写法
-
常用函数
push_back(x)
: 在尾部添加一个元素x
pop_back()
: 删除尾元素size()
: 返回元素个数clear()
: 清空insert(it, x)
: 向vector
的迭代器it
处插入元素x
erase(it)
:删除迭代器it
处的元素erase(first, last)
:删除迭代器区间[first, last)
内的元素
-
细节:
容器内容也是一个STL容器时,记得在> >
之间加空格,
即vector<vector<int> > name;
| set(集合)
集合:内部自动 递增 有序且不含重复元素
红黑树实现
-
头文件
#include<set>
-
用途:
1、需要去重但却不方便直接开数组的情况 -
访问:
只能通过迭代器 (set<typename>::iterator it
) -
常用函数
insert(x)
: 向set
中插入x
,自动递增排序和去重 (O(logN)
)find(value)
: 返回set
中对应值为value
的迭代器(O(logN)
)查找失败时返回st.end()
erase(it)
:删除迭代器it
处的元素 (O(1)
)erase(value)
:其中value
为所需删除元素的值(O(logN)
)erase(first, last)
:删除迭代器区间[first, last)
内元素(O(log(first - last))
)size()
: 返回元素个数(O(1)
)clear()
: 清空 (O(N)
)
-
延伸:
1、如果需要处理元素不唯一的情况,则需使用multiset
2、如需只去重但不排序,C++ 11标准中增加了unordered_set
(以散列代替set
内的红黑树),速度比set
快得多
| string(字符串)
-
头文件
#include<string>
-
用途:
0、 (占位) -
访问:
1、通过下标(从0
到size() - 1
)
2、通过迭代器 (不像其他STL需要参数,string::iterator it
)- 一般通过下标访问即可满足要求,但是部分函数(如
insert()
,erase()
)要求迭代器为参数
- 一般通过下标访问即可满足要求,但是部分函数(如
注:str[i]
与 *(str.begin() + i)
是等价的
只有
string
和vector
中允许使用str.begin()+i
这种迭代器加整数的写法
-
输入输出
- 如果要读入整个
string
字符串,只能用cin
和cout
c_str()
:转为char[]
用printf
输出:printf("%s",str.c_str())
- 如果要读入整个
-
常用函数
-
+
: 拼接 -
==、!=、<、<=、>、>=
: 比较字典序 -
size()/length()
: 返回string
长度 (O(1)
) -
insert(pos, string)
: 在pos
号位置插入字符串string
-
insert(it, it1, it2)
:it
为原字符串的欲插入位置,it2
和it3
为待插字符串的首尾迭代器,即串[it2, it3)
插在it
的位置上 -
erase(it)
:删除迭代器it
处的字符 -
erase(first, last)
:删除迭代器区间[first, last)
内的元素 -
erase(pos, len)
:从pos
位开始删除len
个字符 -
substr(pos, len)
:返回pos
位开始、长度len
的子串(O(len)
) -
find(str2)
:返回str2
在str
第一次出现的位置; 如果str2
不是子串,返回string::npos
(O(nm)
:n
和m
分别为str
和str2
的长度) -
find(str2, pos)
:从str
的pos
位开始匹配str2
,返回值同上 -
string::npos
:作为find()
失配时的返回值 -
replace(pos, len, str2)
:把str
从pos
位开始、长度为len
的子串替换为str2
-
replace(it1, it2, str2)
:把str
的迭代器[it1, it2)
范围的子串替换为str2
(O(str.length()
) -
clear()
:清空
-
| map(映射)
可以将任何基本类型(包括STL)映射到任何基本类型(包括STL);
按键递增排序(红黑树实现)
-
头文件
#include<map>
-
用途:
**1、**如果是字符串到整形的映射,必须使用string
而不能用char[]
- (但是刷PAT时用
printf()
输入的char[]
可以直接作为map<string, type1>
的键值啊!)
**2、**判断大整数或其他类型数据是否存在时,可把
map
当bool
数组使用 - (但是刷PAT时用
-
访问:
1、通过下标(键):例mp['c']
2、通过迭代器 (map<typename1,typename2>::iterator it
)
3、it->first
:访问键;it->second
:访问值 -
常用函数
-
find(key)
:返回键为key
的映射的迭代器,失败返回mp.end()
(O(logN)
:N
为map
中映射的个数) -
push_back(x)
: 在尾部添加一个元素x
-
pop_back()
: 删除尾元素 -
size()
: 返回元素个数(O(1)
) -
clear()
: 清空 (O(N)
) -
insert(it, x)
: 向vector
的迭代器it
处插入元素x
-
erase(it)
:删除迭代器it
处的元素(O(1)
) -
erase(key)
:删除键为key
的元素 (O(logN)
) -
erase(first, last)
:删除迭代器区间[first, last)
内的元素
-
-
延伸
multimap
:map
的键和值是唯一的,而如果一个键需要对应多个值,就可用multimap
unordered_map
: 若只需映射而不按key
排序,C++ 11 标准新增了unordered_map
(以散列代替红黑树实现,速度比map
快得多)
| queue(队列)
-
头文件
#include<queue>
-
用途:
**1、**实现BFS时,可以用queue
,以提高程序准确性 -
访问:
只能通过front()
访问队首元素,通过back()
访问对位元素 -
常用函数
push(x)
:元素x
入队(O(1)
)pop()
: 首元素出队 (O(1)
)front()
:获得队首元素(O(1)
)back()
:获得队尾元素(O(1)
)empty()
:检测是否为空 (O(1)
)size()
: 返回元素个数(O(1)
)
-
清空:
STL中没有实现队列的清空,故若需要实现队列的清空,可用while
循环反复pop()
直到栈空;更常用的方法是重新定义一个队列从而变相实现清空,定义的时间按复杂度是O(1)
-
细节:
- 使用
front()
和pop()
前,必须使用empty()
判断队列是否为空
- 使用
-
延伸
STL的容器中还有两种容器和队列有关,分别是双端队列(deque
)和优先队列(priority_queue
),前者是首尾皆可插入删除的队列,后者是用堆实现的默认将当前队列最大元素置于队首的容器。
| priority_queue(优先队列)
用堆实现,队首元素一定是当前队列中优先级最高的那一个
-
头文件
#include<queue>
-
用途:
1、 解决一些贪心问题
2、 对 Dijstra 算法进行优化(因为优先级队列的本质是 堆) -
访问:
只能通过top()
来访问队首元素(每次必须先用empty()
判断是够为空) -
常用函数
push(x)
:元素x
入队(O(logN)
)pop()
: 首元素出队 (O(logN)
)empty()
:检测是否为空 (O(1)
)size()
: 返回元素个数(O(1)
)
-
优先级设置
-
基本数据类型 的优先级
此处指int
、double
、char
等可直接使用的数据类型
优先队列对它们的优先级设置一般是数字大的优先级高
因此以下两种定义是等价的:priority_queue<int> q;
、priority_queue<int, vector<int>, less<int> > q
第二种定义中:
vector<int>
: 表示承载底层数据结构堆(heap
)的容器,若第一个参数是double
,则此处只需改为vector<double>
;less<int>
: 表示数字大的优先级高,而**greater<int>
**表示数字小的优先级高即 想要优先级队列总是把最小的元素放在队首,则如下定义
priority_queue<int, vector<int>, greater<int> >
**tips:**其实基本数据类型也可按照结构体来写,只不过第三个参数有点区别
-
结构体 的优先级
- 重载运算符(两种)
-
/*写在结构体内*/
//价格高的优先级高( 正好与排序函数sort中的cmp效果相反 )
struct fruit {
string name;
int price;
firend bool operator < (fruit f1, fruit f2) {
return f1.price < f2.price;
}
};
//之后就可以直接定义使用了,其内部已满足价格高的优先级高
priority_queue<fruit> q;
-----------------------------------------------------
/*写在结构体外*/
struct fruit {
string name;
int price;
}f1, f2, f3;
//把小于号改成一对小括号,并将重载的函数用struct包装起来
struct cmp {
bool operator () (fruit f1, fruit f2) {
return f1.price > f2.price;
}
};
//定义时也有变化,把greater<>部分 换成 cmp
priority_queue<fruit, vector<fruit>, cmp > q;
/*
注意:
重载大于号会编译错误,因为从数学上来说只需要重载小于号,
即 f1>f2 等价于 f2<f1,而f1==f2则等价于判断 !(f1<f2) && !(f2<f1)
*/
若结构体内的数据较为庞大(例如出现字符串或数组),建议使用引用来提高效率,此时比较类的参数中需要加上 const
和 &
:
firend bool operator < (const fruit &f1, const fruit &f2) {
return f1.price > f2.price;
}
bool operator () (const fruit &f1, const fruit &f2) {
return f1.price > f2.price;
}
| stack(栈)
-
头文件
#include<stack>
-
用途:
**1、**模拟实现一些递归;(一般程序的栈内存空间很小,用普通函数进行递归会导致程序运行崩溃) -
访问:
只能通过top()
来访问栈顶元素
注:v[i]
与 *(v.begin() + i)
是等价的
只有
string
和vector
中允许使用v.begin()+i
这种迭代器加整数的写法
-
常用函数
push(x)
:元素x
入栈(O(1)
)top()
:获得栈顶元素(O(1)
) 【先用empty()
判断是够为空】pop()
: 弹出栈顶元素 (O(1)
) 【先用empty()
判断是够为空】empty()
:检测是否为空 (O(1)
)size()
: 返回元素个数(O(1)
)
-
清空:
STL中没有实现栈的清空,故若需要实现栈的清空,可用while
循环反复pop()
直到栈空;更常用的方法是重新定义一个栈从而变相实现清空,定义的时间按复杂度是O(1)
| pair(内部有两个元素的结构体)
-
头文件
#include<utility>
or#include<map>
由于
map
的实现涉及pair
,故添加map
头文件会自动添加utility
头文件 -
用途:
1、 代替二元结构体及其构造时间,节省编码时间
2、 作为map
的 键值对 来进行插入 -
定义:
pair<typeName1, typeName2> name;
定义时进行初始化:
pair<string, int> p("haha", 5);
-
访问:
pair
中只有两个元素,分别是first
和second
,按结构体的方式访问即可
pair<string, int> p;
p.first = "haha";
p.second = 5;
cout << p.first << " " << p.second << endl;
- 常用函数
-
比较
==、!=、<、<=、>、>=
:先以
first
大小为标准,当first
相等时采取判别second
的大小
-