问题描述:借助两个栈实现一个队列的基础功能,也是笔试面试中的热门题型之一,最常想到的方法莫过于分别创建两个栈s1和s2,s1用来存放入队元素,s2用来弹出出队元素。其过程大致为:
对于最先想到的方法,翻来覆去的倒的这种算法,多多少少是有优化的地方的。比如:可设置一个计数器count用于显示当前栈中的元素个数,因为其s1倒入s2中时,可将s1的最后一个元素直接弹出,这样的做法减少了一次压栈操作(不用将其压入s2中后再弹出)。其性能并未有什么明显的提升,但确实是一种思路。
方法一:
①入队时,将元素压入s1。
②出队时,判断s2是否为空,如不为空,则直接弹出顶元素;如为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。
#include<iostream>
#include<stack>
using namespace std;
class Queue
{
public:
void Push(const int element);
int Pop();
private:
stack<int> s1;
stack<int> s2;
};
void Queue::Push(const int element)
{
s1.push(element);
}
int Queue::Pop()
{
if (s2.empty())
{
while (!s1.empty())
{
int tmp = s1.top();
s1.pop();
s2.push(tmp);
}
}
//s2栈为空,先将s1全部压进s2,然后弹出栈顶。s2栈若为非空,直接弹出栈顶元素。所以两者的弹出可以合在一起
int back_ele = s2.top();
s2.pop();
return back_ele;
}
方法二:
①入队时,先判断s1是否为空,如不为空,说明所有元素都在s1,此时将入队元素直接压入s1;如为空,要将s2的元素逐个“倒回”s1,再压入入队元素。
②出队时,先判断s2是否为空,如不为空,直接弹出s2的顶元素并出队;如为空,将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。
#include<iostream>
#include<stack>
using namespace std;
class Queue
{
public:
void Push(const int element);
int Pop();
private:
stack<int> s1;
stack<int> s2;
};
void Queue::Push(const int element)
{
if (s1.empty())
{
while (!s2.empty())
{
int tmp = s2.top();
s2.pop();
s1.push(tmp);
}
s1.push(element);
}
if (!s1.empty())
{
s1.push(element);
}
}
int Queue::Pop()
{
if (s2.empty())
{
while (!s1.empty())
{
int tmp = s1.top();
s1.pop();
s2.push(tmp);
}
}
//s2栈为空,先将s1全部压进s2,然后弹出栈顶。s2栈若为非空,直接弹出栈顶元素。所以两者的弹出可以合在一起
int back_ele = s2.top();
s2.pop();
return back_ele;
}
★注:相比较而言:第一种的方法更好一些,因为其避免了反复“倒”栈,仅在需要时才“倒”一次,显得其性能更高。