
1. vector 顺序表
💡 核心要点:vector 是动态变长数组,支持灵活的元素增删、大小调整,可实现一维 / 二维动态数组,通过成员函数操作。
1.1 基础使用
1.1.1 创建方式
- 空数组:
vector<类型> 名字;(如vector<int> a;) - 固定长度 N(元素默认 0):
vector<类型> 名字(N);(如vector<int> a(10);) - 固定长度 N 且元素初始化为 val:
vector<类型> 名字(N, val);(如vector<int> a(100, 10);) - 直接初始化元素:
vector<类型> 名字{元素1, 元素2,...};(如vector<string> a{"a", "b"};) - 二维动态数组(行数固定,列数可变):
vector<类型> 名字[N];(如vector<int> a[5];)
1.1.2 核心成员函数
size():返回实际元素个数;empty():返回布尔值,判断数组是否为空(均需加()调用)begin()/end():返回迭代器(begin = 起始位置,end = 末尾元素下一位),支持范围 for 遍历:for(auto x : a)push_back(x):末尾添加元素;pop_back():末尾删除元素front():返回首元素;back():返回尾元素resize(n):调整数组大小(n > 原大小补0 ,n < 原大小截断尾部)clear():清空所有元素,数组变为空
1.2 专业补充 📚
- vector 底层是连续内存,扩容时会重新分配内存并拷贝元素,可提前用
reserve(n)预留空间优化性能; - 二维 vector 更灵活的写法:
vector<vector<int>> a(n);(行数可动态调整,优于vector<int> a[n]); - 迭代器失效场景:扩容、非末尾插入 / 删除元素时,原有迭代器需重新获取。
1.3 适用场景 & 核心注意 ⚠️
- 头文件:必须包含
<vector>; - 适用场景:需要动态调整大小的数组、不确定元素个数的存储(如刷题临时结果);
- 避坑点:
- 创建指定长度必须用
(),而非[](vector<int> a(10)正确,vector<int> a[10]是创建 10 个空 vector); - 访问元素前需判断长度是否足够,避免越界;
- 创建指定长度必须用
2. 链表 list(数组模拟)
💡 核心要点:竞赛中常用数组模拟单链表(替代 STL 的 list),通过 h/e/ne 三个数组实现,支持高效的插入 / 删除操作,时间复杂度 O (1)。
2.1 基础使用
2.1.1 核心数组定义
h:哨兵头节点(head),初始值通常为 0;e:存储元素值(element),e[id]表示第 id 个节点的元素;ne:存储下一个节点的下标(next),ne[id]表示第 id 个节点的下一个节点下标;id:节点计数,初始值通常为 0。
2.1.2 核心操作
头插法添加元素
cppid++; // 新增节点编号 e[id] = x; // 赋值 ne[id] = ne[h];// 新节点指向原头节点的下一个节点 ne[h] = id; // 头节点指向新节点任意位置 p 后插入元素:
id++; e[id] = x; ne[id] = ne[p]; ne[p] = id;遍历链表
for(int i = ne[h]; i != 0; i = ne[i]) { // 操作e[i] }删除 p 后面的元素
void erase(int p) { // p表示元素的位置 if(ne[p]) { mp[e[ne[p]]] = 0; // 从mp中删除该元素(按需使用) ne[p] = ne[ne[p]]; // 跳过被删除节点 } }
2.2 专业补充 📚
- STL 的list 是双向链表,支持任意位置 O (1) 插入 / 删除,但遍历效率低于 vector(非连续内存),竞赛中极少使用;
- 哨兵节点(h)的作用:避免处理头节点为空的边界情况,简化代码。
2.3 适用场景 & 核心注意 ⚠️
- 适用场景:需要频繁在任意位置插入 / 删除元素的场景(如链表模拟题、邻接表存储图);
- 避坑点:
- 节点编号 id 需从 1 开始(0 作为结束标记),避免与哨兵节点冲突;
- 删除前需判断
ne[p]是否为 0,避免访问空节点; - 数组大小需提前开足够(如 1e5),避免越界;
- STL 的 list 时间复杂度高,竞赛优先用数组模拟。
3. 栈 stack
💡 核心要点:后进先出 ,仅支持栈顶的插入(push)、删除(pop)和访问(top)操作。
3.1 基础使用
- 头文件:
<stack>;- 创建方式:
stack<类型> 名字;(如stack<string> st;);- 核心成员函数:
size()/empty():元素个数 / 判空;push(x):将 x 压入栈顶;pop():删除栈顶元素 ;top():返回栈顶元素 。
3.2 专业补充 📚
- stack 底层默认基于 deque 实现,也可指定底层容器(如
stack<int, vector<int>> st;); - 型应用:括号匹配、表达式求值、深度优先搜索(DFS)。
3.3 适用场景 & 核心注意 ⚠️
- 头文件:
<stack>; - 适用场景:需要 "后进先出" 逻辑的场景(如括号匹配、函数调用栈模拟);
- 避坑点:
- 使用
top()前必须用empty()判断栈是否为空,避免程序崩溃; pop()仅删除元素,不返回值(需先top()再pop())。
- 使用
4. 队列 queue
💡 核心要点: 先进先出 支持队尾插入(push)、队头删除(pop),可访问队头 / 队尾元素。
4.1 基础使用
- 头文件:
<queue>;- 创建方式:
queue<类型> 名字;(如queue<int> q;);- 核心成员函数:
size()/empty():元素个数 / 判空;push(x):将 x 插入队尾;pop():删除队头元素(无返回值);front():返回队头元素;back():返回队尾元素。
4.2 适用场景 & 核心注意 ⚠️
- 适用场景:需要 "先进先出" 逻辑的场景(如 BFS、消息队列);
- 避坑点:使用
front()/back()前需判断队列非空。
5. 优先级队列 priority_queue
💡 核心要点: 有序 ,默认降序(大根堆),插入自动排序,仅能访问 / 删除堆顶(优先级最高)元素。
5.1 基础使用
头文件:
<queue>(无单独头文件);创建方式:
- 默认大根堆:
priority_queue<类型> 名字;(如priority_queue<int> heap;);- 大根堆:
priority_queue<int, vector<int>, less<int>> heap2;;- 小根堆:
priority_queue<int, vector<int>, greater<int>> heap3;;核心成员函数:
size()/empty():元素个数 / 判空;push(x):插入元素并自动排序;pop():删除堆顶元素(无返回值);top():返回堆顶元素;结构体排序(需重载
<运算符)
struct node { int b; bool operator < (const node& x) const { return b > x.b; // 小根堆(b小的优先级高) } }; priority_queue<node> heap;
5.2 专业补充 📚
- 底层是堆(完全二叉树),插入 / 删除时间复杂度 O (logn);
less<int>对应降序(大根堆),greater<int>对应升序(小根堆), 与sort的比较规则相反(sort 默认升序 = less<int>)。
5.3 适用场景 & 核心注意 ⚠️
- 头文件:
<queue>; - 适用场景:动态获取最大值 / 最小值(如 TopK 问题、贪心算法);
- 避坑点:
- 结构体排序仅能重载
<运算符(不能重载>); - 小根堆需指定三个模板参数(类型、底层容器、比较器)。
- 结构体排序仅能重载
6. set 与 multiset
💡 核心要点: 有序无重复 ,++multiset 允许重复元素++,底层为红黑树,支持自动排序、查找、插入、删除,迭代器仅支持 ++/--。
6.1 基础使用
- 头文件:
<set>;- 创建方式:
- set:
set<类型> 名字;(如set<string> s;);- multiset:
multiset<类型> 名字;(如multiset<int> ms;);- 核心成员函数:
size()/empty():元素个数 / 判空;begin()/end():迭代器,支持范围 for 遍历(默认升序);insert(x):插入元素(set 自动去重,multiset 允许重复);erase(x):删除所有值为 x 的元素;++erase(迭代器):删除指定迭代器元素++;find(x):查找 x,返回迭代器(不存在则返回 end ());count(x):返回 x 的出现次数(set 中仅 0/1);lower_bound(x):返回≥x 的最小元素迭代器;upper_bound(x):返回 > x 的最小元素迭代器。
6.2 专业补充 📚
- 迭代器使用需解引用
- 底层是红黑树,操作时间复杂度 O (logn);
- 迭代器仅支持双向移动(++/--),不支持随机访问(如
it+1); - 范围 for 遍历是中序遍历,结果为升序。
6.3 适用场景 & 核心注意 ⚠️
- 头文件:
<set>; - 适用场景:有序去重集合(set)、有序允许重复集合(multiset);
- 避坑点:判断元素是否存在优先用
count(x)(比find(x)便捷)。
7. map 与 multimap
💡 核心要点: 键值对有序集合(键唯一),multimap 允许重复键,底层为红黑树,可通过键快速访问值。
7.1 基础使用
- 头文件:
<map>;- 创建方式:
map<键类型, 值类型> 名字;(如map<string, int> mp;);- 核心特性:
- 键唯一(multimap 允许重复键);
- 方括号访问:****mp["张三"]
= 90;(键不存在则自动插入,值默认初始化);- 核心成员函数:与 set 一致(
insert/erase/find/count等,均针对键操作)。
7.2 专业补充 📚
- 底层是红黑树,按键升序排列,操作时间复杂度 O (logn);
- multimap 不支持方括号访问(键不唯一)。
7.3 适用场景 & 核心注意 ⚠️
- 头文件:
<map>; - 适用场景:键值对映射且键有序(如字典、统计频次);
- 避坑点:避免直接用方括号判断键是否存在(会自动插入),应先用
count()/find()。
8. 哈希表(unordered_set/unordered_map)
💡 核心要点:unordered_set/unordered_map 是无序哈希表,底层为哈希表,操作平均 O (1),接口与 set/map 基本一致,不自动排序。
8.1 基础使用
- 头文件:
<unordered_set>(unordered_set)、<unordered_map>(unordered_map);- 创建方式:
- unordered_set:
unordered_set<类型> 名字;(如unordered_set<int> us;);- unordered_map:
unordered_map<键类型, 值类型> 名字;(如unordered_map<int, string> um;);- 核心成员函数:与 set/map 一致(++无
lower_bound/upper_bound++)。
8.2 专业补充 📚
- 底层是哈希表,平均操作 O (1),最坏 O (n)(哈希冲突);
- 与 set/map 对比:速度更快但无序,set/map 有序但速度稍慢。
8.3 适用场景 & 核心注意 ⚠️
- 头文件:
<unordered_set>/<unordered_map>; - 适用场景:不需要有序、追求快速查找 / 插入 / 删除(如高频判重、键值对查询);
- 避坑点:
- 无序,不能依赖遍历顺序;
- 不支持
lower_bound()/upper_bound(); - 自定义结构体作为键需自定义哈希函数。
总结
- 语法规范 :创建指定长度的 vector 用
()而非[],使用容器成员函数前需用empty()判空,priority_queue 的比较规则与 sort 相反; - 核心特性:vector 是动态数组(连续内存),栈 / 队列是线性结构(LIFO/FIFO),set/map 是有序红黑树,unordered 系列是无序哈希表(更快);
- 竞赛技巧:链表优先用数组模拟(避免 STL list 的高复杂度),判重 / 查询优先用 unordered 系列(O (1)),有序场景用 set/map(O (logn))。