1.用两个栈来实现队列,栈是先进后出的,队列是先进先出的,这时,我们可以用stack1来专门入栈,stack2来专门出栈,具体地:
入队:直接入栈到stack1
出队:检测stack2是否为空,如果为空,则将stack1的所有元素移动到stack2中,
再次判断stack2是否为空,如果为空抛出异常;
如果非空,将stack2的栈顶元素出队。
代码如下:
#include <iostream> #include <stack> using namespace std; //用两个栈实现一个队列stack1专门用来入队 stack2专门用来出队 template<class T>class Queue { public: Queue(void){}; ~Queue(void){}; void AppendTail(const T &ele); T DeleHead(); private: stack<T>stack1; stack<T>stack2; }; //stack1专门用来入栈 template<class T> void Queue<T>::AppendTail(const T &ele) { stack1.push(ele); } //stack2作为临时缓冲,将stack1入栈的元素逆序 然后出栈即可实现先入先出 template<class T> T Queue<T>::DeleHead() { if (stack2.size()<=0)//stack2空 则将stack1的元素都放在stack2中 { while (stack1.size()>0) { T node=stack1.top(); stack2.push(node); stack1.pop(); } } if (stack2.size()==0)//判断栈是否为空 { cout<<"empty"<<endl; throw new exception(); } T RetNode =stack2.top();//返回stack2的栈顶元素 stack2.pop();//出栈 return RetNode; } void main() { Queue<int>*pQu=new Queue<int>(); pQu->AppendTail(1); pQu->AppendTail(2); pQu->AppendTail(3); cout<<pQu->DeleHead()<<endl; pQu->AppendTail(4); pQu->AppendTail(5); cout<<pQu->DeleHead()<<endl; cout<<pQu->DeleHead()<<endl; cout<<pQu->DeleHead()<<endl; cout<<pQu->DeleHead()<<endl; cout<<pQu->DeleHead()<<endl; }
队列是先进先出的,而栈是后进先出的,那么我们如何用两个队列实现栈的操作呢?
方法一:
我们可以让queue1专门用来入栈和出栈操作,让queue2作为储存queue1的n-1个元素,也就是除了最后一个入队元素,然后将queue1中的最后元素出列,然后将queue2中的 n-1个元素放回queue1.
思路:
q1是专职进出栈的,q2只是个中转站
入栈时:直接入队列q1即可
出栈时:把q1的除最后一个元素外全部转移到队q2中,然后把刚才剩下q1中的那个元素出队列。之后把q2中的全部元素转移回q1中。
如下图所:
#include <queue> #include <iostream> using namespace std; template <class T> class Stack { public: Stack(){}; ~Stack(){}; void StackPush(const T&data); T StackPop(); private: queue<T>que1; queue<T>que2; }; //que1专门用来入栈 template<class T> void Stack<T>::StackPush(const T&data) { que1.push(data); } //que2作为临时存储que1的多余变量,当出栈后要将所有元素还给que1 template<class T> T Stack<T>::StackPop() { if (que1.size()<=0) { cout<<"empty"<<endl; throw new exception("empty"); } else//que1的变量大于等于1个时 { while(que1.size()>1)//将最先入n-1个元素的存que2中 { que2.push(que1.front()); que1.pop(); } T RetData=que1.front();//返回最后入的元素 que1.pop(); while(que2.size()>0)//再将que2的元素存回que1 { que1.push(que2.front()); que2.pop(); } return RetData; } } void main() { Stack<int > *pSt=new Stack<int >(); pSt->StackPush(1); pSt->StackPush(2); pSt->StackPush(3); cout<<pSt->StackPop()<<endl; cout<<pSt->StackPop()<<endl; cout<<pSt->StackPop()<<endl; // cout<<pSt->StackPop()<<endl;//抛异常 }
结果如下图:
然后我们发现,如果队列中元素较多时,每当移除一个元素,那么剩余的n-1个元素都要拷贝进queue2,然后再从queue2拷进queue1,这样增加了时间复杂度,那么能不能有其他更好的办法呢?
方法二:
让两个栈都当做出栈或者入栈的队列,当入栈时候,先选定一个que1入栈,当出栈时候将que1的n-1个元素移动que2。那么下一次出栈的队列为que2,再将n-1个元素移动到que1,依次.....
那么入栈时候该选择哪个呢?很显然,入栈也是来回变的,每当有一次出栈操作时,下次入栈时所选的队列都会改变,这时候我们只需要一个标志位flag来选定该入哪个队列就好了。
代码如下:
#include <queue> #include <iostream> using namespace std; template <class T> class Stack { public: Stack(){}; ~Stack(){}; void StackPush(const T&data); T StackPop(); private: queue<T>que1; queue<T>que2; static bool flag;//用来标识该在哪个队列入栈的标识 }; template<class T> bool Stack<T>::flag=true;//初始化为TRUE 在que1中入栈 template<class T> void Stack<T>::StackPush(const T&data) { queue<T>*quTemp=NULL;//用于指向要入栈的队列,注意初始化格式 if (flag)//标识用来决定该入栈到哪个队列 { quTemp=&que1; } else { quTemp=&que2; } quTemp->push(data); } template<class T> T Stack<T>::StackPop() { flag=!flag;//将标识取反 queue<T>*popTemp=NULL;//用于出栈的临时队列 queue<T>*saveTemp=NULL;//用于保存n-1个多余变量的队列 if (que1.size()>=1) { popTemp=&que1; saveTemp=&que2; } else { popTemp=&que2; saveTemp=&que1; } if (popTemp->size()<=0) { cout<<"Empty"<<endl; throw new exception("the stack is empty"); } while(popTemp->size()>1)//出栈的队列中元素大于1个 移动到另一个队列中 { saveTemp->push(popTemp->front()); popTemp->pop(); } T RetVal=popTemp->front();//返回最后一个元素 popTemp->pop(); return RetVal; } void main() { Stack<int> *pSt=new Stack<int>(); pSt->StackPush(1); pSt->StackPush(2); pSt->StackPush(3); cout<<pSt->StackPop()<<endl; cout<<pSt->StackPop()<<endl; pSt->StackPush(4); pSt->StackPush(5); cout<<pSt->StackPop()<<endl; cout<<pSt->StackPop()<<endl; cout<<pSt->StackPop()<<endl; }
运行结果如下图所示: