剑指offer 学习笔记 用两个栈实现队列
面试题9:用两个栈实现队列。队列声明如下,实现它的appendTail和deleteHead函数,分别表示在队尾插入节点和在队列头删除节点。
template <typename T> class CQueue {
public:
CQueue();
~CQueue();
void appendTail(const T &node);
T deleteHead();
private:
stack<T> stack1;
stack<T> stack2;
};
首先分析一下往该队列中插入和删除元素的过程,首先插入一个元素a,不妨把它插入stack1,再向stack1中压入两个元素b、c,此时stack2是空的。此时,我们想从队列中删除一个元素,由于a先进,因此a先出,但a在栈底,我们可以把stack1中所有元素依次先出栈再压入stack2,完成后stack1为空,而stack2的栈顶就是a了。如我们还想出队列,继续弹出stack2的栈顶元素即可。因此,当我们想出队列且stack2不为空时,直接弹出stack2的栈顶元素即可;当stack2为空时,将stack1中所有元素依次弹出并压入stack2,之后再弹出即可。
考虑继续向队列插入元素,我们直接向stack1插入元素即可:
#include <iostream>
#include <stack>
using namespace std;
template <typename T> class CQueue {
public:
void appendTail(const T& node);
T deleteHead();
private:
stack<T> stack1;
stack<T> stack2;
};
template <typename T> T CQueue<T>::deleteHead() {
if (stack2.size() == 0) {
while (stack1.size() > 0) {
stack2.push(stack1.top());
stack1.pop();
}
}
if (stack2.size() == 0) {
throw exception("empty queue");
}
T res = stack2.top(); // 此处不能定义为引用以提高效率,因为栈顶元素在下句代码被弹出
stack2.pop();
return res;
}
template <typename T> void CQueue<T>::appendTail(const T &node) {
stack1.push(node);
}
int main() {
CQueue<int> q;
q.appendTail(1);
q.appendTail(2);
q.appendTail(3);
q.appendTail(4);
q.appendTail(5);
cout << q.deleteHead() << endl;
}
相关题目:
1.用两个队列实现一个栈。分析:我们先往栈中压入元素a,不妨将a放入queue1中,接下来往栈中压入元素b、c,我们将b、c都存入queue1中,这样a位于queue1的队列头,b、c紧随其后。当我们想弹出一个元素时,如上例,应该弹出c,我们就可以把queue1中元素依次出队列再入队列queue2,这样c是queue1中最后一个出队列的,将c删除即可,这样,queue2中从头到尾元素为a、b,弹出b时重复以上步骤即可。当我们想压入元素d时,直接放在有元素的队列的队尾即可,这样再出栈时,按以上步骤出栈的还是d,符合栈的后进先出特点。
#include <iostream>
#include <deque>
using namespace std;
template <typename T> class CStack {
public:
void push(const T &);
T pop();
private:
deque<T> que[2];
};
template <typename T> void CStack<T>::push(const T& t) {
int i = 0;
if (que[i].size() == 0) { // 向有元素的队列插入
i = 1 - i;
}
que[i].push_back(t);
}
template <typename T> T CStack<T>::pop() {
int i = 0;
if (que[i].size() == 0) {
i = 1 - i;
}
if (que[i].size() == 0) {
throw exception("empty stack");
}
while (que[i].size() != 1) {
que[1 - i].push_back(que[i].front());
que[i].pop_front();
}
T res = que[i].front();
que[i].pop_front();
return res;
}
int main() {
CStack<int> s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
cout << s.pop() << endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)