STL小结

​

一、概述

STL全称Standard Template Library,直译出来就是标准模板库。简单来说就是一套盘子、木桶、水杯,随你怎么理解吧,总而言之言而总之就是——容器。放什么的容器?放数据的容器。要我说,数组它也算容器,只不过面对某些特殊情况拿数组去模拟实在是太为难人了,所以就有了STL中多种多样的容器。

二、容器简介

1、vector(动态数组)

 器如其名,就是把静态数组弄活了。

定义很简单:

vector<int> a;//定义了一个空动态数组;
vevtor<int> a(n);//定义了一个长度为n的动态数组(下标从0开始);
vector<int> a(n,0);//定义了一个长度为n、每一个元素为0的动态数组(下标从0开始);
!!!静态数组可不能为空哦

注意:当你数组大小为0或想要在尾部添加一项时...

v.push_back(x)//x为添加的数

我在这里也随便说一句,我能用vector就用vector,因为vector不仅十分灵活,可添可减,而且STL还给我们提供了一系列函数供我们使用,除了时间复杂度有一点点多之外,其他都要比静态数组强。函数打起来太过麻烦,故在此列表陈述:

常用函数使用说明
a.pop_back() 删除末尾元素
a[i] 访问元素
a.size() 返回元素个数
a.begin() 和 v.end() 返回迭代器(开头和结尾)
a.insert(pos,val) 插入元素
a.erase(pos) 删除指定位置元素

!!!注意:

(1)insert和erase在使用时第一个参数是迭代器(即a.begin()+位置整数);
(2)insert可以在pos和val中间加一个参数,即所插入之数的个数;

2、stack(栈)

这个玩意也很简单(至少是理解层面的),他就是先进后出,即我先放进去的数后出来,有点像往木桶中塞东西,木桶只能容一只手通过,于是先塞进去的必然就是后出来。

它的缺点也十分明显:无法实现快速的查找,但是对于括号这种后进去先匹配的玩意儿来说实在是好用至极。

如图:

​编辑

函数不多,简单写一下吧:

差点忘了,先说定义:

stack<int> s;
常用函数使用说明
s.push(x) 入栈
s.pop() 出栈
s.top() 查看栈顶元素
s.empty() 判空
s.size() 栈大小

!!! 当然还有—— 单!调!栈!即——在入栈和出栈过程中保持单调性的特殊栈结构。

停停停停!还有一个小知识:

栈和递归的关系:本质是一回事!

✅ 一句话总结:

递归 = 隐式地使用了栈结构

每一次递归调用函数,系统都会将当前函数的状态压入栈中,直到递归终止条件满足,再按调用顺序反向出栈,逐步回溯。

想到什么了:DFS

3、queue(队列)

可以说是跟栈一样玩意儿,也是不能查找元素,也是在某些范围有极高的适用强度,甚至函数也跟栈有很多相像的地方,只有一个地方有亿一点点不同:它是先进先出。就像排队买票一样,先排队的人先买票,插队是大大的不行滴!

如图:

​编辑

定义真的有必要说吗,没有!

queue<int> s;//只能说是如出一辙
常用函数使用说明
q.push(x) 入队
q.pop() 出队
q.front() 查看队首元素
q.back() 查看队尾元素
q.empty() 判空
q.size() 队列大小

关于队列还有另外一些东西,打在这儿吧:

(1)priority_queue(优先队列)

(2)deque(双端队列)

 

  • priority_queue :适用于需要快速获取最大或最小值的场景,如任务调度、贪心算法等。它通过堆结构实现,队首元素总是当前队列中优先级最高的元素。默认情况下,priority_queue 是一个最大堆,但可以通过自定义比较器实现最小堆。

名称

意义
q.push(x) 入队
q.top() 队首元素
q.pop() 弹出队首元素
1. 大根堆
priority_queue<int> q;

在里面写直接的“int”,表示队内元素按照从大到小排序

2. 小根堆
priority_queue<int, vector<int>, greater<int>> q;
  • deque :适用于需要在队列两端进行高效插入和删除的场景,如滑动窗口、缓存机制等。它支持在头部和尾部进行操作,并且支持随机访问元素,但中间的插入和删除操作效率较低。

还是挺好用的。

4、string(字符串)

熟悉吧?没错,就是这玩意儿,处理字符数组即字符串相关问题相当好用。

定义:

string s;
string s1="hello";
string s2=(5,'a');//即"aaaaa"

!!!注意单个字符应该是'a',即单字母;而字符串应该是"hello",即双引号,不然编译会出错的。

它的函数虽然不如存储数据多,但是用于处理字符串,实在是够用了:

常用函数使用说明
s+=str 拼接
reverse(s.begin(),s.end()) 反转字符串
s.substr(pos,len) 截取子串
s.find(sub) 查找子串位置
s.size() 长度

5、pair(二元组)

过掉简单的的字符串,迎来更加简单的的二元组;这个东西是真简单,就是一次能放两个数据的变量,第一个数据是first,直接用a.first就可以调用,第二个则使用a.second。其实就我个人而言,结构体(struct)似乎更好用。当然,嵌套是它的一般使用方式。

定义:

pair<int,pair<int,int>> b(1, {2,3});
//嵌套就这么用,可以设初始值也可以不设。

!!! 注意:不能直接cin>>a.first,只能先int n;cin>>n;再a.first=n;这也是其它一些容器的问题。

附:在进行pair排序时,默认先排first,first相等再排second,可以合理运用。

6、set(集合)

去重加排序,你说怎么用?

补:unordered_set & multiset

简单说明:

类型有序可重复底层示例定义
set ✔ × 红黑树 set<int> s;
unordered_set × 哈希表(懂否) unordered_set<int> us;
multiset ✔ 红黑树 multiset<int> ms;

set 基本特性:

  • first 存储唯一元素
  • second 自动排序(升序)
  • third 查询、插入、删除时间复杂度为 O(log n)(红黑树实现)

基于以上特性,我一般都只拿它存稳定数据,其内存占用也有点高,且不直接支持修改元素。

常用函数使用说明
s.insert(x) 插入元素(自动去重)
s.count(x) 检查元素是否存在,返回0或1
s.erase(x) 删除元素
s.find(x) 查找元素并返回迭代器
s.lower_bound(x) 返回第一个 ≥x 的元素迭代器
s.upper_bound(x) 返回第一个 >x 的元素迭代器

附:后面两个函数应该只有特特殊环境(such as 配合二分)下才能使用。

所谓应用就是配合其特性好好使用,不过多赘述。

7、map(映射表)

本人认为继动态数组,二元组,字符数组后的又一实用的玩意儿。

补:unordered_map & multimap

简单说明:

类型有序可重复底层示例定义
map ✔ × 红黑树 map<string, int> m;
unordered_map × 哈希表 unordered_map<int, string> um;
multimap ✔ 红黑树 multimap<char, int> mm;

这个东西就是存储键值对并按键自动排序,提供 O(log n) 的查找、插入和删除复杂度,可以通过m[key]来快速查询。key就是定义中的第一项,第二项就是所存储的数据类型。另外,也可以用first & second来查询第一项 & 第二项。

常用函数使用说明
m[key] = val 插入或更新值
m.at(key) 访问值,越界会报错
m.count(key) 判断 key 是否存在,返回0或1
m.find(key) 返回指向 key 的迭代器
m.erase(key) 删除键值对
m.lower_bound(k) 返回第一个 ≥k 的键迭代器
m.upper_bound(k) 返回第一个 >k 的键迭代器

遍历:

for (auto& [key,val]:m)
{
	cout<<key<<" "<<val<<endl;
}
// 旧式写法
for (auto it=m.begin();it!=m.end();it++) 
{
	cout<<it->first<<" "<<it->second<<endl;
}

三、算法简介

类别常用函数示例
排序 sort(begin, end) 升序
稳定排序 stable_sort() 保持相对顺序
查找 find() / binary_search() 线性 / 二分
区间查找 lower_bound() / upper_bound() 前闭后开区间
数值操作 accumulate() , count() , max_element() 求和、计数、最大值
修改容器 reverse() , rotate() , unique() 反转、旋转、去重
其他 next_permutation() , iota() , __gcd() 枚举排列、填充序列、求GCD

看着用吧

附:如要使用sort(a,a+n);的这种形式,则指针或迭代器必须支持随机访问,这边也推荐使用容器的begin()和end()。sort中也可以加排序函数,如:

bool cmp(int x,int y)
{
    return x>y;
}//降序比较函数
int main()
{
    vector<int> a={3,1,2,4};
    sort(a.begin(),a.end(),cmp);//cmp决定排序规则,如此时是降序排列,即若cmp判断为true,那么x就在y前。
    //即此时a内数据为4 3 2 1。
}

所以STL是很简单滴!这就写完小结了,但要做到炉火纯青的运用怕是还要一阵子吧

四、总结

STL(Standard Template Library)是 C++ 标准库的核心组件,提供了一套高效、通用的模板化数据结构和算法,主要包括:容器(如 vector、map、set)、迭代器(用于遍历容器)、算法(如 sort、find)和 函数对象(如仿函数、Lambda)。STL 的设计遵循泛型编程思想,通过迭代器解耦容器与算法,实现高度复用性,同时保证性能(如大多数操作的时间复杂度明确标注)。对我们来说亦是解题的利器!

注:以上内容的优先队列部分复制参考了自己之前写的树与二叉树,应该算原创吧。。。
​
posted @ 2025-09-06 15:19  一只小小的芙厨  阅读(35)  评论(0)    收藏  举报