用两个栈实现一个队列 1、线性表分为:顺序表和链表。 栈:只允许在尾上(即是栈顶)进行插入与删除。 队列:它是在队尾插入,队头删除。 2、栈选数组(即顺序表)结构时(比选链表结构更好):因为选数组结构可以进行size++与size--,而且效率高。 栈选链表结构: 3、队列选数组结构时:选数组结构不好,因为删除时需要整体前移,因为队列是在队头进行删除,删除了队头元素时,其后面所跟的其他元素就需要整体向前移一位。效率较低。 队列选链表结构时:比选数组结构好,因为插入和删除元素时方便。 #include <iostream> #include <stack> #include <assert.h> using namespace std; //2、两个栈实现一个队列 //思路:当两个栈都为空时,只能做入队操作,当两个栈不都为空时,入队、出队操作都可以实现。 // inSta主要用于入栈,outSta主要用于出栈 //过程: // 入队:1、当outSta为空时,入队操作相当于对inSta做入栈操作(包括inSta为空和inSta不为空两种情况) // 2、当inSta为空,outSta不为空(即上一操作为出栈,inSta转移到outSta的元素没有转移回inSta)时,此时先把outSta的所有元素出栈, // 并按照出栈顺序入栈到inSta,然后再把此时要入队列的元素入栈到inSta // PS:不会出现inSta不为空,outSta不为空的情况,这种情况只会在前一操作为入队列的出队列过程中(inSta的元素除栈底元素外全部转移 // 到outSta),然后这一操作执行前outSta为空,执行后,inSta为空 // 出队:1、当inSta、outSta都为空时,队列里面无元素,无法实现出栈 // 2、当inSta不为空,outSta为空时,把inSta除栈底元素外的所有元素出栈,并按照出栈顺序入栈到outSta,把inSta的栈底元素出栈 // 3、当inSta为空,outSta不为空时,说明上一操作为出栈,inSta转移到outSta的元素没有转移回inSta,此时把outSta的栈顶元素出栈即可 // PS:不会出现两个栈都不为空的情况,这种情况只会在前一操作为入队列的出队列时,然后这一操作执行前outSta为空,执行后, // Stack1为空 template<typename T> class TwoStackForQueue { public: TwoStackForQueue() { //利用stack的构造函数完成 } TwoStackForQueue(const TwoStackForQueue<T>& que) { //调用stack的赋值运算符重载/拷贝构造函数 inSta = que.inSta; outSta = que.outSta; } ~TwoStackForQueue() { //这儿不用做什么事情,两个栈开辟的空间由satck释放 } void Push(const T& t) { if (outSta.size() == 0) //说明上一操作为入队操作或队列此时为空 { inSta.push(t); } else { //先把outSta里面的元素按其出栈顺序入栈到inSta while (outSta.size() != 0) { inSta.push(outSta.top()); outSta.pop(); } inSta.push(t); } } void Pop() { assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况 if (outSta.size() == 0) { //把inSta的栈底元素留下,直接出栈它的栈底元素即可 while (inSta.size() != 1) { outSta.push(inSta.top()); inSta.pop(); } inSta.pop(); } //说明上一操作为出栈,此时直接出栈outSta的栈顶元素即可 else { outSta.pop(); } } T& Front() { assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况 if (outSta.size() != 0) { return outSta.top(); } else { //这儿不要图方便,留下inSta的栈底元素不移动,直接返回inSta的栈底元素,因为这样做的话使inSta和outSat都不为空了, //而上面的Push与Pop没有对这种情况进行处理 while (inSta.size() != 0) { outSta.push(inSta.top()); inSta.pop(); } return outSta.top(); } } T& Back() { assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况 if (outSta.size() != 0) { //这儿不要图方便,留下outSta的栈底元素不移动,直接返回outSta的栈底元素,因为这样做的话使inSta和outSat都不为空了, //而上面的Push与Pop没有对这种情况进行处理 while (outSta.size() != 0) { inSta.push(outSta.top()); outSta.pop(); } return inSta.top(); } else { return outSta.top(); } } bool Empty() { if (inSta.size() == 0 && outSta.size() == 0) { return true; } else { return false; } } size_t Size() { //要么两个栈都为空-->返回0,要么一个为空一个不为空-->返回两个栈中不为空的栈的size即可 return inSta.size() > outSta.size() ? inSta.size() : outSta.size(); } //为了测试正确性,写一个输出运算符重载 template<typename T> friend ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que); private: stack<T> inSta; stack<T> outSta; }; template<typename T> ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que) { TwoStackForQueue<T> coutque(que); os << "Queue: "; //根据入队序列输出 inSta栈顶-->最后入队的元素 outSta-->最先入队的元素 //所以先把元素都先入栈到outSta,每次输出outSta的栈顶元素,并把它出栈,直到outSta里面没有元素即可 if (coutque.inSta.size() > 0) { while (coutque.inSta.size() > 0) { coutque.outSta.push(coutque.inSta.top()); coutque.inSta.pop(); } } while (coutque.outSta.size() > 0) { os << coutque.outSta.top() << " "; coutque.outSta.pop(); } os << "NULL"; return os; } void Test() { TwoStackForQueue<int> que; que.Push(0); que.Push(5); que.Push(4); que.Push(1); que.Push(2); que.Push(3); cout << que << endl; que.Pop(); que.Pop(); cout << que << endl; cout << que.Front() << endl; cout << que.Back() << endl; cout << que.Empty() << endl; cout << que.Size() << endl; } int main() { Test(); return 0; } //优化版一 //2、两个栈实现一个队列 //思路:当两个栈都为空时,只能做入队操作,当两个栈不都为空时,入队、出队操作都可以实现。 // inSta只用于入栈,outSta只用于出栈 //过程: // 入队:不管outSta是否为空,都直接把元素入栈到inSta // 出队:1、当inSta、outSta都为空时,队列里面无元素,无法实现出栈 // 2、当outSta为空时,把inSta除栈底元素外的所有元素出栈,并按照出栈顺序入栈到outSta,把inSta的栈底元素出栈 // 3、当outSta不为空时,说明上一操作为出栈,此时把outSta的栈顶元素出栈即可 template<typename T> class TwoStackForQueue { public: TwoStackForQueue() { //利用stack的构造函数构造inSta与outSta即可 } TwoStackForQueue(const TwoStackForQueue& que) { inSta = que.inSta; outSta = que.outSta; } ~TwoStackForQueue() { //inSta和outSta空间的释放由stack类来完成 } void Push(const T& t) { inSta.push(t); } void Pop() { assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况 if (outSta.size() == 0) { //说明此时是第一次执行出对列或之前outSta里面的数据全部被出栈了 while (inSta.size() != 1) { outSta.push(inSta.top()); inSta.pop(); } inSta.pop(); } //说明之前留在outSta里面的元素没有被全部出栈 else { outSta.pop(); } } T& Front() { assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况 if (outSta.size() != 0) { return outSta.top(); } else { //当outSta为空时,说明队首元素即是inSta的栈底元素,返回它即可 while (inSta.size() != 1) { outSta.push(inSta.top()); inSta.pop(); } return inSta.top(); } } T& Back() { assert(inSta.size() != 0 || outSta.size() != 0); //队列为空的情况 if (inSta.size() != 0) { return inSta.top(); } else { //当inSta为空时,说明队尾元素即是outSta的栈底元素,返回它即可 while (outSta.size() != 1) { inSta.push(outSta.top()); outSta.pop(); } return outSta.top(); } } bool Empty() { if (inSta.size() == 0 && outSta.size() == 0) { return true; } else { return false; } } size_t Size() { //返回两个栈的元素个数和 return inSta.size() + outSta.size(); } //为了测试正确性,写一个输出运算符重载 template<typename T> friend ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que); private: stack<T> inSta; stack<T> outSta; }; template<typename T> ostream& operator<<(ostream& os, const TwoStackForQueue<T>& que) { TwoStackForQueue<T> coutque(que); os << "Queue: "; //根据入队序列输出 inSta不为空:inSta栈顶-->最后入队的元素 outSta不为空:outSta栈顶-->最先入队的元素 while (coutque.outSta.size() > 0) { os << coutque.outSta.top() << " "; coutque.outSta.pop(); } while (coutque.inSta.size() > 0) { coutque.outSta.push(coutque.inSta.top()); coutque.inSta.pop(); } while (coutque.outSta.size() > 0) { os << coutque.outSta.top() << " "; coutque.outSta.pop(); } os << "NULL"; return os; } void Test() { TwoStackForQueue<int> que; que.Push(0); que.Push(5); que.Push(4); que.Push(1); que.Push(2); que.Push(3); cout << que << endl; que.Pop(); que.Pop(); cout << que << endl; cout << que.Front() << endl; cout << que.Back() << endl; cout << que.Empty() << endl; cout << que.Size() << endl; } int main() { Test(); return 0; }
本文出自 “10911544” 博客,请务必保留此出处http://10921544.blog.51cto.com/10911544/1773535
原文地址:http://10921544.blog.51cto.com/10911544/1773535