请你仅使用两个队列实现一个后进先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop、empty)。
实现MyStack类:
- void push(int x) 将元素x压入栈顶。
- int pop( ) 移除并返回栈顶元素。
- int top( ) 返回栈顶元素。
- bool empty( ) 如果栈是空的,返回true;否则,返回false。
示例:
输入:[“MyStack”, “push”, “push”, “top”, “pop”, “empty”]
[ [ ], [1], [2], [ ], [ ], [ ] ]
输出:[null, null, null, 2, 2, false]
思路:
栈的原则是先进后出(FILO),而队列的原则是先进先出(FIFO)。我们若是想要用队列模拟实现一个先进先出的栈,那么在出数据的时候必须先将队列中前面的元素先出队列,然后才能拿到最近一次入队列的数据。
也就是说,入数据的时候往队列当中直接入就行了,但是出数据的时候由于我们是要得到最近一次入队列的数据,所以我们应该先将队列中前 n-1(假设一共n个)个元素拿出来,才能拿到最后一个元素,但是前 n-1 个元素又不能直接丢弃,所以我们还需要一个队列用于出数据的时候存储出队列的前 n-1 个元素。
然后下一次再需要出数据的时候,也是先将非空队列中的前 n-1 个元素导入空队列当中,再让最后一个元素出队列。
总结: 入数据的时候往非空的队列入,若两个队列都为空,则随便入哪个队列。出数据的时候先将非空队列中的前 n-1 个元素导入空队列,再将最后一个元素出队列。
代码如下:
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
//构造函数无需编写,使用默认构造函数即可
}
/** Push element x onto stack. */
void push(int x) {
//往非空的队列入数据
if (!_q1.empty())
{
_q1.push(x);
}
else
{
_q2.push(x);
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
queue<int>* emptyQ = &_q1;
queue<int>* nonemptyQ = &_q2;
if (!_q1.empty())
{
swap(emptyQ, nonemptyQ);
}
//将非空队列的前n-1个元素导入空队列
while (nonemptyQ->size() > 1)
{
emptyQ->push(nonemptyQ->front());
nonemptyQ->pop();
}
//获取最后一个元素值
int top = nonemptyQ->front();
nonemptyQ->pop(); //将最后一个元素出队列,即“出栈”
return top; //返回“出栈”元素
}
/** Get the top element. */
int top() {
//“栈顶”元素,即非空队列的最后一个数据
if (!_q1.empty())
{
return _q1.back();
}
else
{
return _q2.back();
}
}
/** Returns whether the stack is empty. */
bool empty() {
return _q1.empty() && _q2.empty(); //两个队列同时为空时,则“栈”为空
}
private:
queue<int> _q1;
queue<int> _q2;
};
/**
* 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();
*/