#创作计划# c++容器:从入门到入土
2025-08-20 10:08:30
发布于:北京
@AC君 求加精
也希望得到大家的支持
第一部分:为什么要学习c++容器
- 容器是c++中管理数据的高效工具
- 容器是就像c++中存放数据的“盒子”
- c++标准库(STL)就提供了多种容器
本篇文章将会讲解STL中最常用的7中容器
- vector 动态数组
- list 双向链表
- map 有序键值对
- set 有序集合
- queue 队列
- stack 栈
- deque 双端队列
第二部分:容器基础——先搞懂这两个概念
什么是STL?
- STL(Standard Template Library)-- 标准模版库 是c++自带的工具集。包含容器、算法、迭代器
- 容器、算法、迭代器,三者缺一不可
什么是迭代器
- 迭代器(Iterator)是访问容器的关键部分
- 由于不同容器底层结构不同,所以就需要一种统一的方式遍历容器,这就是迭代器
第三部分:比赛、写题常用的7个容器详细介绍
如果你不用万能头,一定要在每个代码前面的头文件都加上#include<容器名>
如:include<vector>
第3.1部分:vector
vector 是什么和它的底层原理
- vector是动态数组(动态分配的数组)
- 底层原理:预先分配一块内存,当存满时自动扩容
vector 的优缺点
- 优点:随机访问快
- 缺点:中间插入元素慢
vector 的核心用法
#include <bits/stdc++.h>
// #include<vector>
using namespace std;
int main(){
// 1. 定义和初始化
vector<int> v1;// 空vector
vector<int> v2(3,0);// vector中有3个元素0
vector<int> v3 = {1,2,3};// vector中有3个元素。分别是1 2 3-->初始化列表
// 2.1. 向尾部添加元素
v1.push_back(1);// v1 = {1}
v2.push_back(1);// v2 = {0,0,0,1}
v3.push_back(1);// v3 = {1,2,3,1}
// 2.2 从某一位置删除元素
v2.erase(v2.begin() + 2); // 删除第三个元素(下标为2),v2 = {0,0,1}
// 3.访问某个元素
// 越界时不报错
cout << v1[1] << endl;// 越界,输出为0
cout << v1[0] << endl;// 不越界,输出为1(因为下标为0的那一项就是1)
// 越界时抛异常
cout << v1.at(1) << endl; 越界,抛出异常
cout << v1.at(0) << endl;// 不越界,输出为1(因为下标为0的那一项就是1)
// 4.遍历(迭代器、范围for)
// 要是想知道这项的下标是多少,需要手动维护
// 迭代器方案
int idx1 = 0;
for (vector<int>::iterator it = v2.begin(); it != v2.end(); ++it) {
cout << *it << " " << idx1++ << endl; // 解引用迭代器获取元素
}
// 范围for方案
int idx2 = 0;
for (int num : v3){
cout << num << " " << idx2++ << endl;
}
// 5. 其他函数
// 求vector数组长度
cout << v3.size() << endl;// v3动态数组长度为:4
// 清空所有元素
v1.clear();
cout << v1.size(); // 此时长度是0
return 0;
}
vector 的用途
- 节省内存但仍需完成像数组一样的操作(例如题目描述:n <= 1e6,m <= 1e6,n * m <= 1e6)
- 频繁随机访问
第3.2部分:list
list 是什么和它的底层原理
- list 是双向链表
- 底层原理:每个节点包含数据和前后指针
- 节点在内存中不连续,也就是说不能随机访问
list 的优缺点
- 优点:任意位置插入、删除快
- 缺点:随机访问慢
list 的核心用法
#include <bits/stdc++.h>
// #include<list>
using namespace std;
int main(){
// 1. 定义和初始化
list<int> l1;// 空list
list<int> l2 = {1,2,3};// list中有3个元素。分别是1 2 3-->初始化链表
// 2.1. 插入元素
// 头部
l1.push_front(1);// [1]
// 尾部
l2.push_back(4);// [1,2,3,4]
// 中间,需要迭代器
list<int>::iterator it = l2.begin();
advance(it, 1); // 移动迭代器到索引1
l2.insert(it, 2);// [1,2,2,3,4]
// 2.2 删除元素,仍然需要迭代器
advance(it, 2);
l2.erase(it); // 删除第三个元素(下标为2),[1 2 3 4]
// 3.访问某个元素
// 范围for+手动维护
int idx = 0;
int mb = 1;// 要访问第2个元素
for (int num : l2){
if (idx == mb){
cout << num << endl;// 最终结果:2
break;
}
idx++;
}
// 4.遍历(迭代器、范围for)
// 要是想知道这项的下标是多少,需要手动维护
// 迭代器方案
int idx1 = 0;
for (list<int>::iterator it1 = l2.begin(); it1 != l2.end(); ++it1) {
cout << *it1 << " " << idx1++ << endl; // 解引用迭代器获取元素
}
// 范围for方案
int idx2 = 0;
for (int num : l2){
cout << num << " " << idx2++ << endl;
}
return 0;
}
list 的用途
- 频繁在任意位置插入、删除元素
- 不需要随机访问但需要双向遍历
第3.3部分:queue
queue 是什么和它的底层原理
- queue 是先进先出队列
- 底层原理:基于其它容器实现
queue 的优缺点
- 优点:首尾操作快
- 缺点:随机访问慢、内存开销略大
queue 的核心用法
#include <bits/stdc++.h>
// #include<queue>
using namespace std;
//定义:queue<存储的数据类型> 队列的名字
queue<int> q;
int main() {
q.push(1); //入队,插入到队首
// [1]
q.front(); //返回队首元素的值,为1
q.back(); //返回队尾元素的值,为1
q.pop(); //队首出队
// []
q.empty(); //判断是否为空,为true
q.size(); //返回队列中元素个数,为0
//在取队首(front)、取队尾(back)、队首出队(pop)时,一定要先判断队列不为空,否则会爆RE
return 0;
}
queue 的用途
- 排队问题
- 广度优先搜索
第3.4部分:stack
stack 是什么和它的底层原理
- stack 是后进先出栈
- 底层原理:基于其它容器实现
stack 的优缺点
- 优点:首操作快、DFS清楚
- 缺点:仅支持栈顶操作,无法随机访问或遍历元素;有可能栈溢出
stack 的核心用法
#include <bits/stdc++.h>
// #include<stack>
using namespace std;
//定义:stack<存储的数据类型> 栈的名字
stack<int> s;
int main() {
s.push(1); //入栈,插入栈顶
// [1]
s.top(); //返回栈顶元素的值,为1
s.pop(); //栈顶出队
// []
s.empty(); //判断是否为空,为true
s.size(); //返回栈顶中元素个数,为0
//在取栈顶(top)、出站(pop)时,一定要先判断栈不为空,否则会爆RE
return 0;
}
stack 的用途
- 括号匹配
- 表达式求值
- 撤销操作
- 深度优先搜索
- 初赛有可能考
第3.5部分:map
map 是什么和它的底层原理
- map 是有序键值对
- 底层原理:基于红黑树实现
map 的优缺点
- 优点:可以通过key快速查找value,且默认按key排序
- 缺点:插入、删除效率略低于哈希表
map 的核心用法
#include <bits/stdc++.h>
// #include<map>
using namespace std;
int main(){
// 1. 定义和初始化
map<string, int> scores;
// 格式:map<key的数据类型,value的数据类型> map名
// 2. 添加键值对
// 方案1
scores["Cindy"] = 90;// 此时scores有一项,键为Cindy,值为95
// 方案2
scores.insert({"Alice", 95});// 此时scores有两项,第二项的键为Alice,值为90
// 3.查找某个元素
// 方案1
cout << scores["Alice"] << endl;// 键为Alice那一项的值
// 方案2,这种方案在key不存在的时候不会插入默认值
auto it = scores.find("Cindy");
if (it != scores.end()){
cout << it->second << endl;// 键为Cindy那一项的值
}
// 4.遍历(默认按key升序)
// 要是想知道这项的下标是多少,需要手动维护
for (auto& pair : scores){
cout << pair.first << ":" << pair.second << endl;
// 注意这里默认按key升序排列了,所以虽然元素进入这个map的时候是Cindy在前,但字典序排序后Cindy就在后面了
}
return 0;
}
map 的用途
- 需要通过唯一键查找值的场景
第3.6部分:set
set 是什么和它的底层原理
- set 是有序集合
- 底层原理:基于红黑树实现
set 的优缺点
- 优点:自动排序、查找快、去重方便
- 缺点:不支持随机访问
set 的核心用法
#include <bits/stdc++.h>
// #include<set>
using namespace std;
int main() {
// 定义
set<int> s;
// 格式:set<set中的数据类型> set名
// 插入
s.insert(10);// [10]
s.insert(20);// [20]
// 输出 set 中的元素
// 范围for
for (int num : s) {
cout << num << " ";
}
cout << endl;
// 查找
if (s.find(20) != s.end()) {// 关键
cout << "20在这个set里面" << endl;
} else {
cout << "20不在这个set里面" << endl;
}
// 删除
s.erase(20);//[10]
// 检查是否为空
cout << s.empty();// 由于现在set中还有元素,所以会输出0
// set长度
cout << s.size();// 现在set长度为1
return 0;
}
set 的用途
- 需要自动去重+排序时
第3.7部分:deque
deque 是什么和它的底层原理
- deque 是双端队列
- 底层原理:分段连续存储
deque 的优缺点
- 优点:首尾操作或随机访问快
- 缺点:中间操作慢
deque 的核心用法
#include <bits/stdc++.h>
// #include<deque>
using namespace std;
int main() {
deque<int> d;// 空deque
deque<int> d2(1);// 包含 1 个默认值元素的 deque
deque<int> d3(2, 3);// 包含2个元素3的deque
// 插入元素
// 尾部
d.push_back(10);// [10]
d2.push_back(20);// [0, 20]
// 头部
d3.push_front(30);// [30, 3, 3]
// 删除元素
// 头部
d2.pop_front();// [20]
// 尾部
d3.pop_back();// [30, 3]
// 求长度
int len = d2.size();
int len2 = d3.size();
// 访问元素
for (int i = 0; i < len; ++i) {
cout << d2[i] << " ";
}
cout << endl;
for (int i = 0; i < len2; ++i) {
cout << d3[i] << " ";
}
cout << endl;
// 其他函数
cout << d2.empty() << endl;// d2是否为空,此时为false
d3.clear();// 清空d3
cout << d3.empty() << endl;// 此时为true,因为此前清空过d3
return 0;
}
deque 的用途
- 部分需滑动窗口题目
- 需频繁进行首尾操作
第四部分:结尾
学习STL中的内容不能光靠“学”
还要会“练”,建议找题库的题目专项练一练
学习STL也不可以光靠这个文章(因为文章只讲了常用的7个容器)
所以建议大家上网搜索其他容器,继续学习
全部评论 7
%%%
昨天 来自 北京
0d
昨天 来自 北京
0d
2天前 来自 北京
0虽然我看不太懂,但好像挺厉害的样子,随便d一下吧,支持一下作者
2025-08-16 来自 重庆
0谢谢
2025-08-16 来自 河北
0
%%%
2025-08-16 来自 重庆
0实际上 deque 和 priority_queue 都比 list 常用
2025-08-16 来自 上海
0好,那我等会更一下
2025-08-16 来自 河北
0
d
2025-08-15 来自 河北
0
有帮助,赞一个