由两个栈组成的队列
【题目】
编写一个类,用两个栈实现队列,支持队列的基本操作(add、poll、peek)。
【解法】
使用两个栈,一个栈(stackOne)用来push,压入数据;压入完成后,再pop进另一个栈(stackTwo),这样就完成了数据的“反序”。
【具体实现】
1.声明
#include<iostream>
#include<stack>
using namespace std;
class MyQueue
{
public:
MyQueue(){}
~MyQueue(){}
void add(int elem);
int poll();
int peek();
private:
stack<int> stackOne;
stack<int> stackTwo;
};
2.实现
#include<iostream>
#include<stack>
#include<stdexcept>
#include"MyQueue.h"
using namespace std;
void MyQueue::add(int elem)
{
stackOne.push(elem);
}
/*int MyQueue::poll()
{
int value;
//for(int i=0;i<stackOne.size();i++)//混淆了大小和长度
for(int i=0;i<6;i++)
{
value=stackOne.top();
stackOne.pop();
stackTwo.push(value);
}
value=stackTwo.top();
stackTwo.pop();
return value;
}*/
/**********改进后的poll************/
int MyQueue::poll()
{
int value;
if(stackOne.empty() && stackTwo.empty())
throw runtime_error("Empty Queue!");
else if(stackTwo.empty())//stackTwo空时代表数据传输没有完成
{
while(!stackOne.empty())//stackOne不为空,继续传输
{
value=stackOne.top();
stackOne.pop();
stackTwo.push(value);
}
}
value=stackTwo.top();
stackTwo.pop();
return value;
}
/*int MyQueue::peek()
{
int top = poll();
stackTwo.push(top);
return top;
}*/
/**********改进后的peek************/
int MyQueue::peek()
{
if(stackOne.empty() && stackTwo.empty())
throw runtime_error("Empty Queue!");
else if(stackTwo.empty())//stackTwo空时代表数据传输没有完成
{
while(!stackOne.empty())//stackOne不为空,继续传输
{
int value=stackOne.top();
stackOne.pop();
stackTwo.push(value);
}
}
return stackTwo.top();
}
3.测试
#include <iostream>
#include "MyQueue.h"
using namespace std;
int main()
{
int a[]={1,5,6,2,6,3};
int i;
MyQueue s;
for(i=0;i<3;i++)
{
s.add(a[i]);
}
cout<<"s.peek: "<<s.peek()<<endl;
for(;i<6;i++)
{
s.add(a[i]);
}
for(i=0;i<6;i++)
{
cout<<"s.peek: "<<s.peek()<<endl;
s.poll();
}
return 0;
}
4.运行结果
【总结】
1.这道题最开始第一眼看起来感觉很简单,然后“快速”的就写出来了代码的初稿,最开始在测试代码中也没发现问题(有一方面是没有get测试的点,测试代码写的不好,没有体现出队列的特性)。
2.但在调试中发现运行时会出现异常退出。参考了标准代码后发现自己最开始写的代码对异常现象没有进行处理。并且在对两个栈之间进行数据传输时使用的是for循环,不便调试。这是第二阶段。
3.最后调试通过标准代码后,又来调试自己最开始写的代码,发现仍有异常退出。猜想是两个栈之间进行pop/push时出现了问题。才发现解题思路上出现了问题,当stackOne栈的数据传输到stackTwo栈之后,stackTwo中的顺序已经为队列的顺序,即之后的出列(poll)都应只对stackTwo中的数据进行操作;数据传输只需进行一次。而自己最开始写的代码中没有增加限制条件,导致调用一次就程序就要执行一次数据传输。因此标准代码中的判断栈空/非空的if条件和while条件地位重要。第一次看标准代码时没有深刻理解,综合来看这道题确实比第一题难一些。
【参考资料】
1.左神的《程序员面试代码指南》第一章中的第二个问题“由两个栈组成的队列”。
2.博客园Stan大神的个人博客 https://www.cnblogs.com/PrimeLife/p/5314204.html