面试题9:用两个栈实现队列
// 面试题9:用两个栈实现队列
// 题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数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; };
解题思路:
栈和队列是截然不同的两种结构,栈是后进先出,先进栈的元素会被压到栈底。
队列则是先进先出。
队列末尾添加节点很简单直接在stack1入栈即可。
删除队列的头结点的话,因为头结点被压在stack1的栈底,所以应该全部出栈再压入stack2,stack2栈顶元素出栈即可。
主要是所有情况都要考虑到。
1)队列为空,即stack1和stack2均为空,这个时候应该抛出异常
2)stack1不为空,stack2为空。直接stack1所有元素出栈,再压入stack2,然后stack2栈顶元素出栈即可。
3)stack1不为空/为空,stack2不为空。不管stack1是不是有元素,只要stack2不为空,说明stack2中元素都是顺着排的,像队列一样,
也就不再需要stack1出栈入栈了,直接stack1栈顶元素出栈。
代码可以这样写,只要stack2为空就开始转移stack1的元素,转移完后如果stack2还是空,抛出异常;
否则就直接stack2栈顶元素出栈并返回即可。
伪代码:
template<typename T> void CQueue<T>::appendTail(const T& element) { 将element压入stack1; } template<typename T> T CQueue<T>::deleteHead() { if(stack2为空){ while(stack1不为空){ 保存stack1栈顶元素; stack1栈顶元素出栈; stack1原栈顶元素压入stack2; } } if(stack2为空) throw exception("队列为空"); 保存stack2栈顶元素; stack2栈顶元素出栈; return stack2原栈顶元素; }
c/c++:
template<typename T> void CQueue<T>::appendTail(const T& element) { stack1.push(element); } template<typename T> T CQueue<T>::deleteHead() { //stack2不为空,开始搬运元素 if(stack2.size()<= 0) { while(stack1.size()>0) { T& data = stack1.top(); stack1.pop(); stack2.push(data); } } //搬运后stack2仍为空,抛出异常 if(stack2.size() == 0) throw new exception("queue is empty"); //stack2栈顶元素出栈,返回 T head = stack2.top(); stack2.pop(); return head; }