剑指Offer9——使用双栈模拟队列
剑指Offer9——使用双栈模拟队列
队列Queue是具有FIFO(First in First out)特性的数据结构,栈Stack是具有LIFO(后进先出)特性的数据结构。下面提供一种思路使用双栈来模拟队列。
1. 思路——为何需要用两个栈?
很显然一个普通的栈是无法替代队列的,这是因为先进栈的元素总是后出栈。
如果输入序列是123(假设push和pop不交替进行),输出序列仅为321,与队列恰好是反过来的。那么,我们产生了一个思路,就像是“负负得正”一样,如果增加一个栈来接收上一个栈所pop出的元素,其输出序列就像一个队列一样。这说明使用两个栈模拟队列在理论上是可行的,但是还有一些细节需要注意。(见实现过程)
2. 实现过程叙述
首先我们设置两个栈:inStack和outStack。
当进行入队操作时,直接将入队元素push进inStack。
当进行出队操作时,这里需要进行一些判断:outStack中的元素是来自于inStack,但是不是说元素进入inStack后直接pop并输出到outStack,因为如果outStack内存在元素,其一定要先于目前在inStack内元素输出,如果现在就直接把inStack内元素pop并输出到outStack中会导致元素顺序混乱(不符合FIFO),因此这里要注意:一定要在outStack为空的前提下再从inStack向其输出元素。也就是说若outStack内有元素就先弹出,若没有则先从inStack内弹出并压入outStack栈,再从outStack栈弹出。这个过程体现在CQueue的deleteHead方法中。
3. 代码示例
class CQueue {
// 推荐使用双端队列模拟栈
private Deque<Integer> inStack;
private Deque<Integer> outStack;
public CQueue() {
// 此处使用菱形语法,也可以在菱形内补充Integer
inStack = new ArrayDeque<>();
outStack = new ArrayDeque<>();
}
// 直接push进inStack就好
public void appendTail(int value) {
inStack.push(value);
}
public int deleteHead() {
/** 此处为代码的关键
** 只有当outStack为空且inStack不为空时操作将inStack元素转移进outStack
** 否则会导致顺序变乱
*/
if(outStack.isEmpty()) {
while (!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
}
if (!outStack.isEmpty()) return outStack.pop();
// 如果outStack为空,返回-1
return -1;
}
}
/**
* Your CQueue object will be instantiated and called as such:
* CQueue obj = new CQueue();
* obj.appendTail(value);
* int param_2 = obj.deleteHead();
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理