C++ 容器适配器
什么是容器适配器?
容器适配器是C++ STL提供的一种特殊容器,它们不是直接存储元素,而是基于其他容器实现特定的数据结构和操作接口。容器适配器通过封装其他容器(如vector
、deque
或list
),并限制其功能,从而提供特定的数据结构语义。
C++ STL提供了三种主要的容器适配器:
- 栈(stack):后进先出(LIFO)的数据结构
- 队列(queue):先进先出(FIFO)的数据结构
- 优先队列(priority_queue):元素具有优先级的队列,最高优先级的元素总是首先出队
备注
容器适配器不是独立实现的容器,而是在现有容器基础上提供特定接口的"封装器"。
栈(stack)
栈的基本概念
栈是一种后进先出(LIFO)的数据结构,就像一堆叠放的盘子,只能从顶部添加或移除元素。
栈的操作
push()
:将元素添加到栈顶pop()
:移除栈顶元素top()
:返回栈顶元素的引用empty()
:检查栈是否为空size()
:返回栈中的元素个数
栈的实现与使用
默认情况下,stack
基于deque
容器实现,但也可以使用vector
或list
作为底层容器。
#include <iostream>
#include <stack>
#include <vector>
int main() {
// 默认基于deque实现的栈
std::stack<int> s1;
// 基于vector实现的栈
std::stack<int, std::vector<int>> s2;
// 添加元素
s1.push(10);
s1.push(20);
s1.push(30);
std::cout << "栈顶元素: " << s1.top() << std::endl; // 输出: 30
std::cout << "栈的大小: " << s1.size() << std::endl; // 输出: 3
// 弹 出栈顶元素
s1.pop();
std::cout << "弹出后的栈顶元素: " << s1.top() << std::endl; // 输出: 20
// 遍历并清空栈
std::cout << "栈中所有元素: ";
while (!s1.empty()) {
std::cout << s1.top() << " ";
s1.pop();
}
std::cout << std::endl; // 输出: 20 10
return 0;
}
栈的应用场景
- 函数调用管理:程序执行时的函数调用栈
- 表达式求值:如中缀表达式转换为后缀表达式
- 括号匹配检查:验证括号是否正确配对
- 撤销操作:许多程序的撤销功能
实际案例:括号匹配检查
#include <iostream>
#include <stack>
#include <string>
bool isBalanced(const std::string& expr) {
std::stack<char> s;
for (char c : expr) {
if (c == '(' || c == '[' || c == '{') {
s.push(c);
} else if (c == ')' || c == ']' || c == '}') {
if (s.empty()) return false;
char top = s.top();
if ((c == ')' && top != '(') ||
(c == ']' && top != '[') ||
(c == '}' && top != '{')) {
return false;
}
s.pop();
}
}
return s.empty();
}
int main() {
std::string expr1 = "{[()]}";
std::string expr2 = "{[(])}";
std::cout << expr1 << " 是否匹配: " << (isBalanced(expr1) ? "是" : "否") << std::endl;
std::cout << expr2 << " 是否匹配: " << (isBalanced(expr2) ? "是" : "否") << std::endl;
return 0;
}
输出:
{[()]} 是否匹配: 是
{[(])} 是否匹配: 否
队列(queue)
队列的基本概念
队列是一种先进先出(FIFO)的数据结构,类似于现实生活中的排队,先到的人先服务,后到的人后服务。
队列的操作
push()
:将元素添加到队尾pop()
:移除队头元素front()
:返回队头元素的引用back()
:返回队尾元素的引用empty()
:检查队列是否为空size()
:返回队列中的元素个数
队列的实现与使用
默认情况下,queue
基于deque
容器实现,但也可以使用list
作为底层容器。
#include <iostream>
#include <queue>
#include <list>
int main() {
// 默 认基于deque实现的队列
std::queue<int> q1;
// 基于list实现的队列
std::queue<int, std::list<int>> q2;
// 添加元素
q1.push(10);
q1.push(20);
q1.push(30);
std::cout << "队头元素: " << q1.front() << std::endl; // 输出: 10
std::cout << "队尾元素: " << q1.back() << std::endl; // 输出: 30
std::cout << "队列大小: " << q1.size() << std::endl; // 输出: 3
// 移除队头元素
q1.pop();
std::cout << "移除后的队头元素: " << q1.front() << std::endl; // 输出: 20
// 遍历并清空队列
std::cout << "队列中所有元素: ";
while (!q1.empty()) {
std::cout << q1.front() << " ";
q1.pop();
}
std::cout << std::endl; // 输出: 20 30
return 0;
}
队列的应用场景
- 缓冲区管理:如打印任务队列
- 广度优先搜索(BFS):图算法中的广度优先遍历
- 任务调度:操作系统中的进程调度
- 消息队列:异步消息处理系统
实际案例:用队列实现广度优先搜索
#include <iostream>
#include <queue>
#include <vector>
// 简化的无向图结构
struct Graph {
int vertices;
std::vector<std::vector<int>> adjacencyList;
Graph(int v) : vertices(v), adjacencyList(v) {}
void addEdge(int src, int dest) {
adjacencyList[src].push_back(dest);
adjacencyList[dest].push_back(src);
}
// 广度优先搜索
void BFS(int startVertex) {
std::vector<bool> visited(vertices, false);
std::queue<int> q;
visited[startVertex] = true;
q.push(startVertex);
std::cout << "BFS 遍历结果: ";
while (!q.empty()) {
int current = q.front();
q.pop();
std::cout << current << " ";
// 访问所有邻接节点
for (int adjacent : adjacencyList[current]) {
if (!visited[adjacent]) {
visited[adjacent] = true;
q.push(adjacent);
}
}
}
std::cout << std::endl;
}
};
int main() {
Graph g(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(2, 3);
g.addEdge(2, 4);
g.addEdge(3, 4);
g.addEdge(3, 5);
g.BFS(0);
return 0;
}
输出:
BFS 遍历结果: 0 1 2 3 4 5