STL 容器总结笔记

STL 容器分为两大类:序列式容器关联式容器

一、序列式容器

按照元素插入的顺序存储,不会自动排序。

容器 底层结构 特点
vector 动态数组 支持下标随机访问;适合尾部插入
array 静态数组 原生数组的标准化封装;大小固定,不能扩容
deque 基于 vector 双端队列,分段连续空间,支持两端频繁插入和删除
list 双向链表 支持在中间任意位置 O(1) 插入和删除
forward_list 单向链表 list 节省一半指针内存;只能单向遍历
stack 基于 vector 栈;先进后出(LIFO)
queue 基于 deque 队列;先进先出(FIFO)
priority_queue 基于堆(vector 优先队列;基于堆排序,元素按优先级出队

二、关联式容器

元素按照某种规则组织,支持高效查找。分为有序和无序两类。

1. 有序关联容器(基于红黑树)

查找时间复杂度:O(log n)

容器 存储内容 是否允许重复键
set 仅键(key) ❌ 不允许
multiset 仅键(key) ✅ 允许
map 键值对(key-value),按 key 排序 ❌ 不允许
multimap 键值对(key-value),按 key 排序 ✅ 允许

2. 无序关联容器(基于哈希表)

查找时间复杂度:O(1) (平均)

容器 存储内容 是否允许重复键
unordered_set 仅键(key) ❌ 不允许
unordered_multiset 仅键(key) ✅ 允许
unordered_map 键值对(key-value) ❌ 不允许
unordered_multimap 键值对(key-value) ✅ 允许

其他

std::string 有短字符串优化,在短字符串时使用对象内部的一个小数组,达到十几二十个字节长度的阈值时把字符串拷贝到堆内存上,原本的数组用来存储指针和 size + capacity。
std::inplace_vector 在 C++26 中加入的动态固定数组,capacity 固定,size 动态,初始化时在对象内部分配内存(对象在哪内存就在哪,栈、堆或全局区,主要是栈上),其他和 vector 保持一致。也就是无法像 vector 一样扩容,也不用像 arrary 一样在初始化时构造全部元素。

总结

STL容器分为两大类:
第一大类是序列式容器:首先第一个 Vector 动态数组,可以根据下标进行随机的访问,适用于在尾部插入的情况;然后第二种 Array 是对原生数组的标准化封装,是静态数组,无法像 Vector 一样扩容;然后第三种 deque 双端队列,主要是用来支持在两端频繁插入删除操作;然后第四种 List 双向链表,可以支持在中间频繁的插入和删除,时间复杂度是 O(1);然后第五种是 ForwardList 单向链表,它比 List 双向链表节省了一部分内存;然后第六种是基于 Vector 实现的栈 Stack,用于先进后出;然后第七种是基于 deque 的 Queue 队列,是先进先出;然后第八种是优先队列 PriorityQueue,是利用堆排序实现的一个有顺序的队列。
然后第二大类就是关联式容器,它也分为两类:第一类是有序的,基于红黑树进行排序,分别是 Set 和 MultiSet 还有 Map 和 MultiMap。Set 存储的是键,根据键值进行排序;Map 是根据键值对的键来排序;Multi 代表可以允许重复的键。因为基于红黑树,它们的查找效率是 O(log n)。然后是无序的,基于哈希表的关联式容器,分别是 unordered_set 和 unordered_multiset 还有 unordered_map 和 unordered_multimap,是基于哈希表的容器,它们的查找时间就是 O(1)。