Skip to content

第1章 STL 标准模板库总览 ​

在 C++ 编程中,STL(Standard Template Library,标准模板库)是不可或缺的工具集,它封装了大量通用的数据结构和算法,遵循"泛型编程"思想,具有跨平台、高效、可复用的特点,旨在帮助开发者减少重复编码,专注于核心业务逻辑。


🎯 本章学习目标 ​

学完本章,你将能够:

  1. 说出 STL 的三大核心组成(容器、算法、迭代器)及其作用
  2. 区分序列式容器、关联式容器、容器适配器三大类
  3. 掌握 vector、list、deque 三种序列式容器的特点与区别
  4. 掌握 set、map 系列关联式容器的四种变体及选型方法
  5. 掌握 stack、queue、priority_queue 三种容器适配器的适用场景
  6. 理解 pair 的基本用法及其与 map/set 的关系
  7. 根据实际需求选择最合适的容器进行编程
  8. 熟练使用各容器的增删改查、遍历等基本操作
  9. 了解各容器的底层实现原理与性能特点
  10. 在算法竞赛和日常开发中灵活运用 STL 解决问题

🗺️ 本章知识图谱 ​

STL 标准模板库
├── 三大核心组件
│   ├── 容器(Containers)—— 数据存储的载体
│   ├── 算法(Algorithms)—— 操作数据的方法
│   └── 迭代器(Iterators)—— 容器与算法的桥梁
├── 序列式容器
│   ├── vector(动态数组)
│   ├── list(双向链表)
│   └── deque(双端队列)
├── 关联式容器
│   ├── set 系列
│   │   ├── set(有序、去重)
│   │   ├── unordered_set(无序、去重)
│   │   ├── multiset(有序、可重复)
│   │   └── unordered_multiset(无序、可重复)
│   └── map 系列
│       ├── map(有序、key唯一)
│       ├── unordered_map(无序、key唯一)
│       ├── multimap(有序、key可重复)
│       └── unordered_multimap(无序、key可重复)
├── 容器适配器
│   ├── stack(栈,LIFO)
│   ├── queue(队列,FIFO)
│   └── priority_queue(优先队列)
└── 基础工具
    └── pair(键值对基础)

一、STL 核心组成 ​

STL 的核心由三大组件构成,三者相互配合,形成完整的开发体系:

  1. 容器(Containers):存储数据的载体,决定数据的存储方式和组织形式,是 STL 最常用的部分;
  2. 算法(Algorithms):操作容器中数据的方法(如排序、查找、插入、删除),与容器解耦,可灵活适配;
  3. 迭代器(Iterators):容器与算法的桥梁,提供统一的元素访问接口,让算法无需关心容器类型。

二、核心容器分类与导航 ​

STL 容器按存储方式和功能,主要分为三大类。

1. 序列式容器 ​

按插入顺序存储,元素位置由插入顺序决定,不依赖元素值:

章节容器特点适用场景学习难度
第2章vector(动态数组)连续内存,随机访问 O(1),尾插 O(1),中间插入 O(n)频繁访问、尾部插入删除、需要排序⭐ 入门
第3章list(双向链表)非连续内存,任意位置插入删除 O(1),不支持随机访问频繁修改、无需随机访问⭐⭐ 基础
第4章deque(双端队列)分段连续内存,双端操作 O(1),随机访问 O(1)头尾都需要高效操作⭐⭐ 基础

2. 关联式容器 ​

按关键字(key)存储,支持快速查找,核心用于去重、映射:

章节容器特点适用场景学习难度
第5章set 系列以元素值为关键字,支持去重(部分类型允许重复)去重、有序查找、集合操作⭐⭐ 基础
第6章map 系列以键值对(key-value)存储,实现关键字到值的映射关键字映射、通过 key 查找 value⭐⭐⭐ 进阶

3. 容器适配器 ​

基于其他容器封装,提供特定操作接口,屏蔽多余功能:

章节容器特点适用场景学习难度
第7章stack(栈)先进后出(LIFO),仅支持栈顶操作括号匹配、递归模拟、逆序输出⭐ 入门
第8章queue(队列)先进先出(FIFO),仅支持队尾插入、队头删除BFS、任务排队、消息队列⭐ 入门
第9章priority_queue(优先队列)按优先级排序,每次取出优先级最高的元素TopK 问题、任务调度⭐⭐⭐ 进阶

4. 基础工具 ​

章节工具特点适用场景学习难度
第10章pair(键值对)两个值的组合,支持字典序比较存坐标、存名次+名字、map元素类型⭐ 入门

三、🚀 学习路径建议 ​

📌 章序 ≠ 学序:本书章序按容器分类编排(序列式 → 关联式 → 容器适配器 → 基础工具), 便于同类对比与查阅;下面给出的是按难度由浅入深排列的学习顺序。建议先按学序通读一遍, 之后再按章序查阅、横向对比。

第一阶段:基础入门(建议 2-3 天) ​

目标:掌握最常用的容器,能解决基础问题

  1. pair(第10章)—— 最基础的工具,先理解"键值对"概念
  2. vector(第2章)—— 最常用的序列式容器,掌握连续内存的特点
  3. stack(第7章)—— 最简单的容器适配器,理解 LIFO 思想

第二阶段:进阶提升(建议 3-4 天) ​

目标:掌握主要容器类型,能应对大多数算法题

  1. queue(第8章)—— 理解 FIFO 思想,学习 BFS 应用
  2. list(第3章)—— 理解链表结构,对比 vector 的差异
  3. deque(第4章)—— 理解分段连续内存,掌握双端操作
  4. set 系列(第5章)—— 掌握四种 set 的区别与选型
  5. map 系列(第6章)—— 掌握键值对映射的用法

第三阶段:深入精通(建议 2-3 天) ​

目标:掌握高级容器,理解底层原理

  1. priority_queue(第9章)—— 理解堆结构,掌握 TopK 等经典问题
  2. 综合练习 —— 多种容器配合使用的复杂场景(第1章实战练习 + 附录 D 综合自测)

四、📊 各容器难度分级与出题频率 ​

章节容器难度出题频率常见题型
第10章pair⭐★★★☆☆选择题、填空题
第2章vector⭐★★★★★选择题、编程题、阅读题
第7章stack⭐★★★★☆选择题、编程题(括号匹配)
第8章queue⭐★★★☆☆选择题、编程题(BFS)
第3章list⭐⭐★★★☆☆选择题、判断题
第4章deque⭐⭐★★☆☆☆选择题、判断题
第5章set⭐⭐★★★★☆选择题、编程题、阅读题
第6章map⭐⭐⭐★★★★☆选择题、编程题、阅读题
第9章priority_queue⭐⭐⭐★★★☆☆选择题、编程题(TopK)

五、📝 实战练习 ​

本章的 8 道练习题覆盖全书九种容器,题型包括选择题、判断题、程序阅读题与编程题,用于检验"看到问题能否选对容器"这一核心能力。所有题目均配有答案与解析,折叠在题目下方,建议先独立完成再对照。

练习题 1(多选题) ​

题目: 下列容器中,哪些不支持用下标 [] 随机访问元素?(多选)

A. vector B. deque C. list D. stack

🔑 点击查看答案与解析

答案: C、D

解析: vector 与 deque 都支持随机访问(O(1)),提供 operator[];list 是双向链表,只能沿指针逐个移动,访问第 k 个元素是 O(n),不提供 [];stack 是容器适配器,本身就不提供任何随机访问接口(连遍历都不支持)。因此 C、D 两项在事实上均满足"不支持用下标 [] 访问"。若题目限定单选,通常取 list 为标准答案,但严格来说 stack 同样不支持。


练习题 2(选择题) ​

题目: 需要按 key 快速查找 value,数据量很大(10⁶ 级),且不要求按 key 有序,应优先选择哪个容器?

A. map B. unordered_map C. multimap D. set

🔑 点击查看答案与解析

答案: B

解析: map / set 底层是红黑树,查找 O(log n) 且自动有序;unordered_map 底层是哈希表,平均查找 O(1),在"不要求有序 + 数据量大"的场景下最快。注意 unordered_* 的最坏情况会退化到 O(n),但平均表现最好。


练习题 3(选择题) ​

题目: 关于 priority_queue<int> 的默认行为,下列说法正确的是?

A. 底层容器默认是 vector,默认是大顶堆 B. 底层容器默认是 deque,默认是大顶堆 C. 底层容器默认是 vector,默认是小顶堆 D. 底层容器默认是 list,默认是小顶堆

🔑 点击查看答案与解析

答案: A

解析: priority_queue 的默认声明是 priority_queue<T, vector<T>, less<T>>,底层容器为 vector,比较方式为 less,即大顶堆(堆顶是最大元素)。若要小顶堆需写成 priority_queue<int, vector<int>, greater<int>>。注意 list 不能作底层容器(堆需要随机访问)。


练习题 4(判断题) ​

题目: stack 和 queue 都提供迭代器,可以用范围 for 遍历所有元素( )

🔑 点击查看答案与解析

答案: 错误

解析: stack、queue、priority_queue 均为容器适配器,刻意屏蔽了迭代器,只能访问栈顶 / 队头(priority_queue 只能访问堆顶),不支持遍历。若需要遍历,应直接用底层容器(vector、deque、list 等)。


练习题 5(判断题) ​

题目: 对于 vector,size() 的返回值一定小于或等于 capacity() 的返回值( )

🔑 点击查看答案与解析

答案: 正确

解析: size() 是当前元素个数,capacity() 是当前已分配内存能容纳的元素个数。vector 会预留额外空间以减少扩容次数,因此恒有 size() <= capacity()。reserve(n) 只改 capacity 不改 size,resize(n) 会同时改变 size(必要时也改 capacity)。


练习题 6(判断题) ​

题目: map 容器中存储的每一个元素,其类型都是 pair<const Key, T>( )

🔑 点击查看答案与解析

答案: 正确

解析: map 的元素就是 pair:用 p->first 取 key、p->second 取 value。其中 key 带 const 修饰——不可通过迭代器修改 key,否则会破坏红黑树的有序性;value 可以修改。


练习题 7(程序阅读题) ​

题目: 阅读以下代码,写出输出结果。

cpp
#include <iostream>
#include <vector>
#include <set>
using namespace std;

int main() {
    vector<int> v = {3, 1, 2, 1};
    set<int> s(v.begin(), v.end());
    cout << s.size() << " " << *s.begin() << endl;
    return 0;
}
🔑 点击查看答案与解析

答案: 3 1

解析: set 由迭代器区间构造时会自动去重 + 升序排序,v 中的 {3,1,2,1} 变为 {1,2,3},故 s.size() 为 3;s.begin() 指向最小元素,解引用得 1。输出为 3 1。


练习题 8(编程题) ​

题目: 输入 n 个整数,统计每个整数出现的次数,并按数字从小到大的顺序输出"数字 次数"。请选用最合适的 STL 容器完成。

**输入格式:**两行。第一行一个整数 n,第二行 n 个整数。 **输出格式:**若干行,每行一个整数及其出现次数,用空格隔开,按整数从小到大排列。

样例输入:

7
3 1 4 1 5 9 2

样例输出:

1 2
2 1
3 1
4 1
5 1
9 1
🔑 点击查看答案与解析

参考代码:

cpp
#include <iostream>
#include <map>
using namespace std;

int main() {
    int n;
    cin >> n;
    map<int, int> mp;
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        mp[x]++;          // 不存在的 key 会自动插入,value 默认 0
    }
    for (auto& p : mp) {  // map 按 key 升序遍历
        cout << p.first << " " << p.second << endl;
    }
    return 0;
}

解析: 本题同时需要"计数"和"按 key 有序输出",用 map 一步到位——mp[x]++ 自动完成插入与累加,遍历时天然升序,无需再排序。若只计数不要求有序,可改用 unordered_map(平均 O(1));若数值范围很小且连续,也可用 vector 计数。


六、📊 考点总结表 ​

知识点重要程度出题形式易错点
STL 三大组件(容器 / 算法 / 迭代器)⭐⭐⭐选择题、判断题把迭代器误当作容器的一部分
序列式 / 关联式 / 容器适配器分类⭐⭐⭐⭐⭐选择题把 stack、queue 误归为序列式容器
支持随机访问的容器(vector、deque)⭐⭐⭐⭐选择题以为 list 也能 []
有序容器(set/map)vs 无序容器(unordered_*)⭐⭐⭐⭐⭐选择题、判断题混淆 O(log n) 与平均 O(1)
去重能力(set/map 系;multiset/multimap 不去重)⭐⭐⭐⭐选择题以为 multiset 去重
适配器屏蔽迭代器,不可遍历⭐⭐⭐⭐判断题试图遍历 stack
容器选型:按需求反推容器⭐⭐⭐⭐⭐选择题、编程题一律用 vector,忽略复杂度
常见复杂度对照(O(1) / O(log n) / O(n))⭐⭐⭐⭐选择题把 unordered_* 的最坏 O(n) 当成常态

┌──────────────────────────────────────────┐ │ STL 容器选型速记卡 │ ├──────────────────────────────────────────┤ │ 要随机访问 + 尾插 → vector │ │ 要头尾都快 → deque │ │ 要中间频繁插删 → list │ │ 要排序 + 去重 → set │ │ 要排序 + 允许重复 → multiset │ │ 要 key→value 映射 → map │ │ 要极致查找、不计顺序 → unordered_map │ │ 要后进先出 → stack │ │ 要先进先出(BFS) → queue │ │ 要每次取最大 / 最小 → priority_queue │ │ 要两个值绑成一组 → pair │ ├──────────────────────────────────────────┤ │ 口诀:查得快用哈希,要有序用红黑树; │ │ 头尾动用 deque,中间动用 list; │ │ 只取一头用适配器,要遍历就别用栈。 │ └──────────────────────────────────────────┘


---

## 七、💡 学习建议

1. **动手写代码**:STL 是工具,光看不练等于没学。每个容器都要亲手写一遍增删改查。
2. **对比学习**:学习新容器时,主动和已学容器对比,找出异同点。
3. **理解底层**:不仅要会用,还要理解底层实现(如 vector 扩容、红黑树、哈希表),这样才能写出高效代码。
4. **刷题巩固**:在洛谷、LeetCode 等平台找对应标签的题目练习,学以致用。
5. **选型思维**:拿到一个问题,先思考"用什么容器最合适",而不是上来就用 vector。

---

## 八、🍎 生活比喻

如果把 STL 容器比作**交通工具**:

- **vector** 就像**公交车**——容量大、按顺序坐、中途上下车麻烦(中间插入慢)
- **list** 就像**出租车**——随时可以上下车(任意位置插入快),但不能随便跳着坐(无随机访问)
- **deque** 就像**地铁**——两头都有门(双端操作快),车厢是连起来的(支持随机访问)
- **set** 就像**自动排序的书架**——书放进去自动按编号排好,找起来很快
- **map** 就像**字典**——按拼音(key)找字(value)
- **stack** 就像**摞盘子**——最后放上去的最先拿走
- **queue** 就像**排队买票**——先来的先买
- **priority_queue** 就像**VIP 通道**——优先级高的先服务
- **pair** 就像**一双筷子**——两个配成一对使用

掌握了这些"交通工具",你就能根据不同的"出行需求"(编程需求),选择最合适的工具,写出高效、优雅的代码!

---

## ⭐ 必背速记卡

百炼成钢,融会贯通