双栈模拟队列需分in_stack和out_stack:in_stack负责入队,out_stack负责出队;仅当out_stack为空时才将in_stack全部倒序转移,确保均摊o(1)。

为什么用双栈模拟队列必须分“入栈”和“出栈”两个角色
单个栈只能后进先出,没法直接取队首;双栈的本质是让一个栈专注接收新元素(in_stack),另一个栈专注提供队首访问(out_stack)。只有当 out_stack 为空时,才把 in_stack 全部倒过去——这个“批量转移”摊掉了每次出队的开销。
关键点在于:每个元素最多被 push 和 pop 各两次(一次进 in_stack,一次进 out_stack,再各弹出一次),所以均摊下来仍是 O(1)。
push() 和 pop() 的具体实现逻辑
push(x) 直接压入 in_stack,无条件 O(1)。
pop() 需要检查 out_stack 是否为空:
- 不为空 → 直接
out_stack.pop() - 为空 → 把
in_stack所有元素逐个pop并push到out_stack,再执行一次out_stack.pop()
注意:不能每次 pop() 都去检查 in_stack 还剩多少,只看 out_stack 是否空;也不能在 push() 里做任何转移操作——那会破坏均摊性质。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
front() 和 empty() 容易踩的坑
front() 不是简单返回 out_stack.top() 就完事:如果 out_stack 为空,必须先触发一次转移(和 pop() 中的逻辑一致),否则读到的是未定义值。
empty() 必须同时检查两个栈:in_stack.empty() && out_stack.empty()。只看其中一个会误判——比如 in_stack 里还有元素但 out_stack 空着,此时队列非空。
常见错误现象:front() 崩溃或返回垃圾值,往往是因为没处理 out_stack 为空的分支;empty() 返回 true 却还能 pop(),说明漏判了 in_stack。
C++ 实现中 std::stack 的几个细节
用 std::stack<int></int> 即可,不需要手写栈;但要注意:
-
std::stack默认底层是std::deque,性能足够,无需换std::vector - 转移时用
while (!in_stack.empty()) { out_stack.push(in_stack.top()); in_stack.pop(); },别用 for 循环配 size()——因为pop()会改 size - 不要在
front()或pop()里加额外的assert或日志,它们会被高频调用,影响均摊分析
最常被忽略的是:转移操作一旦开始,就必须清空整个 in_stack,哪怕只为了取一个 front ——这是保证后续多次 pop() 都能 O(1) 的前提。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










