容器适配器进阶:从栈到队列的C++模拟实现技巧
·
容器适配器进阶:从栈到队列的C++模拟实现技巧
一、容器适配器核心概念
容器适配器通过封装底层容器(如deque或list),提供特定接口实现受限访问:
-
栈:后进先出(LIFO)结构,支持操作:
push(): 元素入栈pop(): 栈顶出栈top(): 访问栈顶元素 $$ \text{栈操作复杂度} = O(1) $$
-
队列:先进先出(FIFO)结构,支持操作:
push(): 元素入队尾pop(): 队首出队front()/back(): 访问首尾元素 $$ \text{队列操作复杂度} = O(1) $$
二、栈的模拟实现
template <typename T, typename Container = std::deque<T>>
class MyStack {
private:
Container c; // 底层容器(默认deque)
public:
void push(const T& value) {
c.push_back(value);
}
void pop() {
if (!empty()) c.pop_back();
}
T& top() {
return c.back();
}
bool empty() const {
return c.empty();
}
size_t size() const {
return c.size();
}
};
关键技巧:
- 选择
deque作为默认容器:支持$O(1)$复杂度的两端操作 - 禁用不相关接口:隐藏底层容器的
insert()等非栈操作 - 异常安全:
pop()前检查空栈状态
三、队列的模拟实现
template <typename T, typename Container = std::deque<T>>
class MyQueue {
private:
Container c; // 底层容器
public:
void push(const T& value) {
c.push_back(value);
}
void pop() {
if (!empty()) c.pop_front();
}
T& front() {
return c.front();
}
T& back() {
return c.back();
}
// size()和empty()实现同栈
};
进阶技巧:
- 容器选择策略:
deque:默认选择,内存非连续但高效list:需频繁中间插入时使用
MyQueue<int, std::list<int>> customQueue; - 迭代器控制:禁用底层容器的随机访问迭代器,防止破坏FIFO特性
- 移动语义优化:
void push(T&& value) { c.push_back(std::move(value)); }
四、性能对比与选型
| 操作 | 栈(deque) | 队列(deque) | 队列(list) |
|---|---|---|---|
push() | $O(1)$ | $O(1)$ | $O(1)$ |
pop() | $O(1)$ | $O(1)$ | $O(1)$ |
| 内存局部性 | 高 | 高 | 低 |
选型建议:
- 栈:优先选择
deque(缓存友好) - 队列:
- 99%场景使用
deque - 需频繁中间插入时用
list - 避免
vector(队首删除$O(n)$)
- 99%场景使用
五、特殊场景实现
循环队列(固定容量):
template <typename T, size_t N>
class CircularQueue {
private:
std::array<T, N> data;
size_t head = 0, tail = 0, count = 0;
public:
void push(const T& value) {
if (count == N) throw std::overflow_error("Queue full");
data[tail] = value;
tail = (tail + 1) % N;
++count;
}
void pop() {
if (count == 0) throw std::underflow_error("Queue empty");
head = (head + 1) % N;
--count;
}
// ...其他接口
};
优势:内存预分配,无动态内存开销,适合嵌入式系统
通过封装底层容器并限制接口,容器适配器在保持高性能的同时提供了简洁的抽象层。实际开发中应优先使用标准库的
stack/queue,理解其实现原理有助于处理特殊需求场景。
更多推荐
所有评论(0)