C++标准模版库
本文最后更新于:2 个月前
STL即标准模板库(Standard Template Library),隶属于C++标准库,包含了一些常用的模板化的数据结构和算法。STL作为模板,拥有极强的兼容性和普适性,大大提高了我们编写代码的效率,使得其在各大算法比赛中都得到了广泛的应用。
本文将STL的学习分为两个板块:container
和algorithm
,各个板块只介绍一些在ACM/ICPC等比赛中常用的函数和功能,如果哪里有内容错误还请同学们海涵和反馈。
容器container
一、向量Vector
std::vector
是STL提供的能够存放任意类型的、内存连续的、可变长度(动态)的数组,可以提供线性复杂度的插入和删除。
Vector的优良特性
- 可以动态分配内存
vector
不像c++
中普通数组一样需要在定义时设定大小,支持动态扩容,即数组的大小会随着你的插入/删除而变大/变小- 允许存储的size也要比普通数组大
- 便利的初始化
- 自带常用的函数
Vector使用方法
1.构造函数
为了可以使用vector,请在你的头文件中包含#include<vector>
1 |
|
2.元素的增删改
v.push_back(element)
:在尾部插入元素elementv.pop_back()
:在尾部删除一个元素v.insert(pos,n,element)
:在pos位置前增加n个相同的元素element,n可省略不写,默认添加一个v.erase(begin,end)
:删除v中[begin,end)
范围内的所有元素v.clear()
:清除所有元素
3.元素的访问
v.at(pos)
:返回v中pos位置的引用v.front()
:返回v中首元素的引用v.back()
:返回v中尾元素的引用v.data()
:返回指向数组第一个元素的指针
4.迭代器
迭代器(Iterator)用来访问和检查STL容器中的对象,可以看作是一个数据指针
学过指针的朋友可以很简单的理解这里hahah
本文章暂时只介绍常用的一些迭代器,感兴趣的同学可以自学更多
v.begin()
:返回指向v中首元素的迭代器,其中*begin=front
v.end()
:返回指向v中尾元素的迭代器,其中*end=back
5.长度和容量
v.empty()
:若v为空返回true
,非空返回false
v.size()
:返回v的元素个数(长度)v.resize()
:改变v的长度
6.容器的遍历
以下才是我们经常写的玩意
1 |
|
二、双端队列Deque
std::deque
是STL提供的双端队列数据结构。
vector
对于头部的插入删除效率低,数据量越大,效率越低;deque
相对而言,对头部的插入删除速度回比vector
快
vector
访问元素时的速度会比deque
快,这和两者内部实现有关
Deque的优良特性
- 随机访问的时间复杂度为常数$O(1)$
- 在结尾或起始插入或移除元素的时间复杂度均为常数$O(1)$
- 插入或溢出元素的时间复杂度同vector一样为线性$O(n)$
Deque使用方法
1.构造函数
为了可以使用deque,请在你的头文件中包含#include<deque>
1 |
|
2.元素的增删改
d.push_back(element)
:在尾部插入元素elementd.push_front(element)
:在头部插入元素elementd.pop_back()
:在尾部删除一个元素d.pop_front()
:在头部删除一个元素d.insert(pos,n,element)
:在pos位置前增加n个相同的元素element,n可省略不写,默认添加一个d.erase(begin,end)
:删除d中[begin,end)
范围内的所有元素d.clear()
:清除所有元素
3.元素的访问
d.at(pos)
:返回d中pos位置的引用d.front()
:返回d中首元素的引用d.back()
:返回d中尾元素的引用d[pos]
:访问d中pos位置的值
4.长度和容量
d.empty()
:若d为空返回true
,非空返回false
d.size()
:返回d的元素个数(长度)d.resize()
:改变d的长度
5.容器的遍历
1 |
|
三、双向链表List
std::list
是 STL 提供的双向链表数据结构。能够提供线性复杂度的随机访问,以及常数复杂度的插入和删除。
list
的使用方法与deque
基本相同,但是由于list
本质是链表,不允许人们随机访问它,所以它与deque
增删操作和访问的复杂度不同。
list
的迭代器、长度、元素增删及修改相关的函数与deque
相同,因此不作详细介绍。
List使用方法
由于链表的特性,若想访问中间元素,必须使用迭代器才能进行(不能随机访问),常用的两个元素访问函数如下:
l.front()
:访问第一个元素l.back()
:访问最后一个元素
四、关联式容器Set
std::set
是STL提供的一种关联式容器,所有元素都会在插入时自动被排序。
set
和数学概念中的集合含义相同,不允许容器中存在相同元素,若将要插入的元素在集合中存在,则无法插入。
set
内部采用红黑树实现。平衡二叉树的特性使得set
非常适合处理需要同时兼顾查找、插入与删除的情况,因为它的搜索、移除和插入均为对数复杂度$O(logn)$。
Set的优良特性
- 增删改查的时间复杂度非常优秀,均为对数级,懂自懂
- 自动进行排序和查重操作,省了很多麻烦
Set使用方法
为了可以使用set/muliset
,请在你的头文件中包含#include<set>
1.元素的增删改
s.insert(element)
:当s中没有element时,将该元素插入set中s.erase(element)
:删除值为element的所有元素,并返回删除元素的个数s.erase(pos)
:删除迭代器为 pos 的元素,要求迭代器必须合法s.erase(begin,end)
:删除s中[begin,end)
范围内的所有元素s.clear()
:清空集合
2.元素的查找和统计
s.count(element)
:统计s中元素值为element的个数,在set中该值为0或1s.find(element)
:若s中存在element会返回该元素的迭代器,否则返回end()
empty()
返回容器是否为空size()
返回容器内元素个数
3.set指定排序规则
1 |
|
Mulitset
mulitset
也存在于头文件set
中唯一与set不同的是,set不允许容器中有重复的元素,而multiset允许容器中有重复的元素
五、Pair
std::pair
是标准库中定义的一个类模板。用于将两个变量关联在一起,组成一个“对”,而且两个变量的数据类型可以是不同的。当你需要返回成对出现的数据时,可能要用到pair嗷
Pair使用方法
p.first
:访问pair的第一个数据(key),该元素起到索引作用p.second
:访问pair的第二个数据(value)
Pair创建方法
pair的创建不需要头文件,以下是pair创建的两种方法
pair<type, type> p ( value1, value2 )
pair<type, type> p = make_pair( value1, value2 )
1 |
|
六、有序键值对容器Map
std::map
中的所有元素都是pair
,所有元素都会根据元素的键值自动排序
map
内部采用红黑树实现,红黑树的好处懂自懂如果你需要存储一些键值对,那就可以考虑使用
map
Map的优良特性
- 一对一处理数据提供了便捷
- map内部已进行自动排序
Map使用方法
1.构造函数
为了可以使用map,请在你的头文件中包含#include<map>
1 |
|
2.元素的增删改
m.insert(pair<T,T>)
:在容器中插入元素m.erase(key)
:删除容器中值为key的元素m.erase(pos)
:删除pos迭代器所指的元素,返回下一个元素的迭代器m.erase(begin,end)
:删除m中[begin,end)
范围内的所有元素,返回下一个元素的迭代器m.clear()
:清空map
3.元素的查找和统计
m.count(key)
:统计key的元素个数,返回非0及1m.find(key)
:查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回end()m.empty()
返回容器是否为空m.size()
返回容器内元素个数
Multimap
map和multimap区别:
map不允许容器中有重复key值元素,multimap允许容器中有重复key值元素
七、栈Stack
std::stack
是STL提供的一种后进先出(LIFO)的容器适配器,仅支持查询或删除最后一个加入的元素(栈顶元素),不支持随机访问,且为了保证数据的严格有序性,不支持迭代器。
Stack使用方法
1.构造方法
为了可以使用stack,请在你的头文件中包含#include<stack>
1 |
|
2.常用函数
top()
访问栈顶元素(如果栈为空,此处会出错)push(x)
向栈中插入元素 xpop()
删除栈顶元素size()
查询容器中的元素数量empty()
询问容器是否为空
八、队列Queue
std::queue
是STL提供的一种先进先出(FIFO)的容器适配器,仅支持查询或删除第一个加入的元素(队首元素),不支持随机访问,且为了保证数据的严格有序性,不支持迭代器。
1.构造方法
为了可以使用queue,请在你的头文件中包含#include<queue>
1 |
|
2.常用函数
front()
访问队首元素(如果队列为空,此处会出错)push(x)
向队列中插入元素 xpop()
删除队首元素size()
查询容器中的元素数量empty()
询问容器是否为空
算法algorithm
STL提供了非常多的实现算法的模板函数(查找、排序、操作),本版块将只介绍一些包含在
<algorithm>
常用的函数。完整的函数列表请单击链接:戳我友情提醒:aogorithm函数的范围定义为
[first, last)
,其中last
指代要查询或修改的最后元素的后一个元素。
一、排序Sort
sort()
作为algorithm
中最常用(自认为)的模板函数,在竞赛中若无特殊要求一般都会使用该函数对序列进行排序操作,时间复杂度达到$O(nlogn)$,很秀
sort使用方法
1 |
|
函数中有三个参数,分别为first
,last
,comp
.
使用sort后以不降序排序范围 [first, last)
中的元素。不保证维持相等元素的顺序,若不自定义comp
则默认为less<T>()
,即从小到大排序,也可以写入greater<T>()
,使得从大到小排序。
如果看上面的这些不太直观,下面给出一些实例化的使用方法:
1 |
|
二、查找Find
find
:顺序查找。find(v.begin(), v.end(), value)
,其中value
为需要查找的值find_end
:逆序查找。find_end(v.begin(), v.end(), value)
binary_search
:二分查找。binary_search(v.begin(), v.end(), value)
,其中value
为需要查找的值lower_bound
:在一个有序序列中进行二分查找,返回指向第一个 大于等于 的元素的位置的迭代器。如果不存在这样的元素,则返回尾迭代器。lower_bound(v.begin(),v.end(),x)
upper_bound
:在一个有序序列中进行二分查找,返回指向第一个 大于 的元素的位置的迭代器。如果不存在这样的元素,则返回尾迭代器。upper_bound(v.begin(),v.end(),x)
三、操作Operation
reverse
:翻转数组、字符串。reverse(v.begin(), v.end())
或reverse(a + begin, a + end)
unique
:去除容器中相邻的重复元素。unique(ForwardIterator first, ForwardIterator last)
,返回值为指向 去重后 容器结尾的迭代器,原容器大小不变。与sort
结合使用可以实现完整容器去重random_shuffle
:随机地打乱数组。random_shuffle(v.begin(), v.end())
或random_shuffle(v + begin, v + end)
next_permutation
:将当前排列更改为 全排列中的下一个排列。如果当前排列已经是 全排列中的最后一个排列(元素完全从大到小排列),函数返回false
并将排列更改为 全排列中的第一个排列(元素完全从小到大排列);否则,函数返回true
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!