C++容器适配器
C++ 容器适配器详解
容器适配器(Container Adapters)是 C++ 标准库中的一种特殊容器,通过封装现有容器并限制其接口,提供特定数据结构的特性(如栈、队列等)。它们本身不是独立的容器,而是基于其他容器(如 deque
、vector
、list
)实现的适配器模式的应用。
一、容器适配器的核心特点
- 接口受限
仅暴露符合目标数据结构特性的操作(如栈的push
、pop
、top
)。 - 组合而非继承
通过内部持有底层容器(如deque
)实现功能,而非继承。 - 不支持迭代器
无法直接遍历元素,仅能通过适配器的接口操作。 - 底层容器可定制
可指定适配器使用的底层容器类型(需满足特定要求)。
二、标准库中的容器适配器
C++ 提供了三种容器适配器:
stack
(栈)、queue
(队列)、priority_queue
(优先队列)。
1. stack
(栈:LIFO 后进先出)
-
默认底层容器:
deque
-
支持操作:
s.push(x) // 压栈 s.pop() // 弹栈(不返回元素) s.top() // 查看栈顶元素 s.empty() // 是否为空 s.size() // 元素数量
-
示例:
#include <stack> #include <vector>std::stack<int> s1; // 默认使用 deque std::stack<int, std::vector<int>> s2; // 使用 vector 作为底层容器s1.push(10); s1.push(20); std::cout << s1.top(); // 输出 20 s1.pop(); // 移除 20
-
底层容器要求:
必须支持back()
、push_back()
、pop_back()
(如vector
、deque
、list
)。
2. queue
(队列:FIFO 先进先出)
-
默认底层容器:
deque
-
支持操作:
q.push(x) // 入队 q.pop() // 出队(不返回元素) q.front() // 队首元素 q.back() // 队尾元素 q.empty() q.size()
-
示例:
#include <queue> #include <list>std::queue<int> q1; // 默认使用 deque std::queue<int, std::list<int>> q2; // 使用 listq1.push(10); q1.push(20); std::cout << q1.front(); // 输出 10 q1.pop(); // 移除 10
-
底层容器要求:
必须支持front()
、back()
、push_back()
、pop_front()
(如deque
、list
)。
3. priority_queue
(优先队列:元素按优先级排序)
-
默认底层容器:
vector
-
支持操作:
pq.push(x) // 插入元素 pq.pop() // 移除最高优先级元素 pq.top() // 查看最高优先级元素 pq.empty() pq.size()
-
示例:
#include <queue> #include <functional> // 用于 greater<int>// 默认是大顶堆(降序) std::priority_queue<int> pq1; // 小顶堆(需指定底层容器和比较函数) std::priority_queue<int, std::vector<int>, std::greater<int>> pq2;pq1.push(30); pq1.push(10); pq1.push(20); std::cout << pq1.top(); // 输出 30(最大值)pq2.push(30); pq2.push(10); std::cout << pq2.top(); // 输出 10(最小值)
-
底层容器要求:
必须支持随机访问迭代器(如vector
、deque
),且需指定比较函数(默认std::less<T>
)。
三、容器适配器 vs 普通容器
特性 | 容器适配器 | 普通容器(如 vector、deque) |
---|---|---|
接口 | 受限,仅暴露特定操作 | 完整,支持迭代器、随机访问等 |
数据结构特性 | 严格遵循栈、队列等行为 | 通用容器,无特定行为约束 |
迭代器支持 | 不支持 | 支持 |
底层实现 | 基于其他容器封装 | 直接管理内存和元素 |
四、底层容器选择建议
stack
- 默认
deque
:平衡头尾操作效率。 - 若需要连续内存:选择
vector
(但pop
时可能触发内存重分配)。
- 默认
queue
- 默认
deque
:高效的头尾插入删除。 - 若需链表特性:选择
list
。
- 默认
priority_queue
- 默认
vector
:堆操作依赖随机访问。 - 避免使用
list
(不支持随机访问)。
- 默认
五、应用场景
stack
- 函数调用栈、括号匹配、表达式求值(逆波兰式)。
queue
- 任务调度、BFS 广度优先搜索、缓冲池。
priority_queue
- 任务优先级调度、Dijkstra 最短路径算法、Top K 问题。
六、自定义比较函数(以 priority_queue
为例)
// 自定义结构体
struct Task {int priority;std::string name;
};// 自定义比较函数(优先级小的先出队)
struct CompareTask {bool operator()(const Task& a, const Task& b) {return a.priority > b.priority; // 小顶堆}
};std::priority_queue<Task, std::vector<Task>, CompareTask> task_queue;task_queue.push({3, "Clean"});
task_queue.push({1, "Urgent"});
std::cout << task_queue.top().name; // 输出 "Urgent"
七、总结
- 容器适配器是对现有容器的封装,提供特定数据结构的行为约束。
stack
、queue
、priority_queue
分别对应栈、队列、优先队列的经典操作。- 灵活选择底层容器以满足不同场景的性能需求。
- 优先使用适配器而非手动实现数据结构,确保代码简洁且符合标准规范。