题目: 用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。
template <typename T> class CQueue
{
public:
CQueue(void);
~CQueue(void);
// 在队列末尾添加一个结点
void appendTail(const T& node);
// 删除队列的头结点
T deleteHead();
private:
stack<T> stack1;
stack<T> stack2;
};
解题思路: 首先这个题目要完成两个栈实现队列,其次还涉及到C++类和模板的一些知识,先说前面: 我们知道,栈是一种后入先出的结构,而队列恰恰相反,是一种先入先出的结构,需要用栈实现队列,这意味着我们有现成的push和pop可以用,以实现入队和出队。
现在有两个栈stack1和stack2,我们向stack1依次压入a,b,c三个值,stack2为空:
此时出栈的话,顺序为c,b,a,但是出队的顺序应该是a,b,c,为了实现想要的出队顺序,我们可以把stack1里面的内容依次压入stack2中:
此时再将stack2内的内容做出栈,将弹出a:
下面讨论再次入队的情况,将d压入stack1,此时两个栈的情况:
此时出队的话,在stack2中还有值的话,直接出栈stack2,弹出b,c。此时stack2中已经没有值了,需要再次从stack1中出栈到stack2中入栈,然后再次stack2的出栈,弹出d。这与队列的出队形式完全相同:
我们可以根据上面的实验整理出一个编程思路,如果stack2中没有值,就做stack1到stack2的压栈,如果有就做stack2的出栈,而不管stack1有没有值都可以做入栈。
下面需要考虑的是C++的模板,使用模板的目的就是能够编写与类型无关的代码,在上面例子中使用了a,b,c,d,那么在实例化对象时T就行该是char,比如实例化一个叫做queue的对象:
CQueue<char> queue;
此外,由于deleteHead函数return不为空,所以他的类型是T,此外appendTail和deleteHead都是在类内声明,类外定义的函数,所以在定义函数时要加类名。
代码实现
template <typename T> CQueue<T>::~CQueue(void)
{
}
template<typename T> void CQueue<T>::appendTail(const T& element)
{
stack1.push(element);
}
template<typename T> T CQueue<T>::deleteHead()
{
if(stack2.size()<= 0)
{
while(stack1.size()>0)
{
T& data = stack1.top();
stack1.pop();
stack2.push(data);
}
}
if(stack2.size() == 0)
throw new exception("queue is empty");
T head = stack2.top();
stack2.pop();
return head;
}