用两个栈实现队列、用两个队列实现栈
题1:用两个栈实现队列
算法分析
栈的特点是先进后出,而队列的特点是先进先出。那么如何用栈来实现队列呢?
先看第一个栈:
1 2 3 4
根据先进后出原则,逐个出栈然后存储到下一个栈:
4 3 2 1
此时,再进行出栈,输出的将是:
4 3 2 1
这和最原始的栈内存"1 2 3 4"的队列化输出结果:"4 3 2 1"一致了!也就是,先进来的4元素,也先出去了!
算法设计
设计两个栈,第一个栈作为数据栈用于存储数据,第二个栈用于反转顺序!
对于由两个栈实现的队列,如果要返回队首的时候,就将第一个数据栈把数据都扔给第二个反转栈用于反转,随后就可以让先进来的栈尾元素到达栈首,此时返回栈首其实就是返回队首!
需要注意的是:
- 每次出队列前,都需要清空第一个数据栈,放到反转栈,这是为了保持次序
- 出队列结束后,为了下一个元素入进入队列顺序不乱,还需要让反转栈的元素重新倒回数据栈
题目描述和AC代码

cpp
class MyQueue {
private:
stack<int> inStk;
stack<int> outStk;
void turnToStack(stack<int>& inStk, stack<int>& outStk) {
while (!outStk.empty()) {
inStk.push(outStk.top());
outStk.pop();
}
}
public:
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
inStk.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
turnToStack(outStk, inStk);
int ret = outStk.top();
outStk.pop();
turnToStack(inStk, outStk);
return ret;
}
/** Get the front element. */
int peek() {
turnToStack(outStk, inStk);
int ret = outStk.top();
turnToStack(inStk, outStk);
return ret;
}
/** Returns whether the queue is empty. */
bool empty() {
return inStk.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/

题2:用两个队列实现栈
为了能让队列实现栈,能否借助栈实现队列的思路进行反转呢?答案是否定的!
因为队列压根起不到反转的效果,于是这里需要重新设计算法!
算法分析
对于一个栈:
1 2 3 4
首先输出的应该是 1 ,因为 1 是最后一个进来的,要先出去!
那么,先用一个数据队列存储栈元素,队列的元素序列是
1 2 3 4
但是此时的队首是 4 而不是 1 怎么办呢?
再设计一个转存队列,用于存储队尾前的全部元素,例如:
2 3 4
这时候,数据队列里就只有 1 这一个元素了,此时的队首就是栈首!然后处理完后,再将转存队列的内容返回到数据队列中,因为队列不会改变次序,所以数据队列会成为:
2 3 4
这就是删除栈首的结果!
算法设计
设计两个队列,一个数据队列,一个缓存队列。
第一个数据队列存储栈数据,当需要弹栈的时候,将数据队列除了最后一个元素以外的数据都放到缓存队列!然后数据队列就只有一个元素了,就是最后进入的那个元素,就直接弹出即可,此时就实现了 "后进先出" !
需要注意的是:
- 缓存只能缓存前 n - 1 个元素,不能把要弹栈的元素都缓存了
- 弹栈完成后,要将缓存的内容倒回数据队列,否则下一个数据入栈的时候,顺序会乱
题目描述及AC代码

cpp
class MyStack {
private:
queue<int> inQue;
queue<int> outQue;
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
inQue.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
while (1 != inQue.size()) {
outQue.push(inQue.front());
inQue.pop();
}
int ret = inQue.front();
inQue.pop();
while (!outQue.empty()) {
inQue.push(outQue.front());
outQue.pop();
}
return ret;
}
/** Get the top element. */
int top() {
while (1 != inQue.size()) {
outQue.push(inQue.front());
inQue.pop();
}
int ret = inQue.front();
outQue.push(inQue.front());
inQue.pop();
while (!outQue.empty()) {
inQue.push(outQue.front());
outQue.pop();
}
return ret;
}
/** Returns whether the stack is empty. */
bool empty() {
return inQue.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
