栈和队列都是比较经常使用的数据结构。栈的应用很是的普遍,好比说,递归函数的实现就是借助于栈保存相关的数据。操做系统中每一个线程也会使用栈来保存函数调用涉及到的一些参数和其余变量等。栈最大的一个特色就是先进后出(FILO—First-In/Last-Out)。
队列和栈不一样的是,队列是一种先进先出(FIFO—first in first out)的数据结构。node
对应的STL中都有实现了的方法。面试
栈的相关方法:数据结构
入栈,s.push(x) 出栈,s.pop() 访问栈顶,s.top() 判断栈空,s.empty() 访问栈中的元素个数,s.size() |
队列的方法与栈大同小异,列举以下:app
入队,q.push(x) 出队,q.pop() 访问队首元素,q.front()、访问队尾元素,q.back() 判断队列空,q.empty() 访问队列中的元素个数,q.size() |
注意,二者的pop()方法,仅仅删除栈顶和队列首元素,并不返回,如需截获元素,在pop()方法以前使用top()或者front()方法。函数
用两个栈实现队列,请实现两个函数appendTail和deleteHead,完成在队列尾部插入结点和在队列首部删除结点的功能。模板定义以下:spa
1 template <typename T> class CQueue 2 { 3 public: 4 CQueue(void); 5 ~CQueue(void); 6 7 // 在队列末尾添加一个结点 8 void appendTail(const T& node); 9 10 // 删除队列的头结点 11 T deleteHead(); 12 13 private: 14 stack<T> stack1; 15 stack<T> stack2; 16 };
分析:操作系统
这道题是要求经过两个“先进后出”的操做完成“先进先出”的功能。下面这个例子比较形象的给出了实现的过程。线程
起初的时候,两个栈都为空,那么只要有元素来,那么默认插入到第一个栈。这是,若是要求删除一个元素,那么元素已经不在栈顶,在第一个栈中确定没法直接删除了,此时咱们发现第二个栈尚未派上用场,这里用到了,把第一个栈中的元素压入到第二个栈中,能够发现原来在第一个栈中栈底的元素已经出如今第二个栈的栈顶上,因此删除的功能就实现了。若是这个时候,“队列”里还有元素,咱们还能够继续出队,并且,如今要出队的元素就在第二个栈的栈顶,因此直接出栈便可。code
分析到如今,下面给出总结:若是栈2不为空,同时又须要出队,那么顺其天然直接弹出便可。若是栈2为空,那么从栈1中逐个弹出压入,那么完整的实现了先进先出的功能。blog
具体的流程和代码实现以下:
1 template<typename T> void CQueue<T>::appendTail(const T& element) 2 { 3 stack1.push(element); 4 } 5 6 template<typename T> T CQueue<T>::deleteHead() 7 { 8 if(stack2.size()<= 0) 9 { 10 while(stack1.size()>0) 11 { 12 T& data = stack1.top(); 13 stack1.pop(); 14 stack2.push(data); 15 } 16 } 17 18 if(stack2.size() == 0) 19 throw new exception("queue is empty"); 20 21 T head = stack2.top(); 22 stack2.pop(); 23 24 return head; 25 }
用两个队列实现栈。
分析:
结合下图,咱们分析一下具体的流程,搞清楚了相关的流程,那么对应的操做就明晰了。
起初的时候,两个队列都是空的,那么当“栈”要压入一个元素,咱们就默认将该元素压入到队列1中。接下来继续压入剩余的元素。
接下来考虑,若是咱们想要弹出一个元素如何操做。栈中要求出栈的为栈顶元素,那么即为最后插入的元素,可是该元素在队列的尾部,必需要求前面的元素出队后才能访问,说到这里,你也就发现思路的:出队前面的元素,到另外一个队列中,那么就能够在原队列中弹出惟一的元素了。
如今咱们再考虑另外一个状况,队列里面还有元素,“栈”又进来了新的元素,那么就将新元素,压入到存在元素的那一个队列中,剩余的操做,上面已经提到了,同样的操做,看图也许就清晰多了。
1 template <typename T> class CStack 2 { 3 public: 4 CStack(void); 5 ~CStack(void); 6 7 // 在队列末尾添加一个结点 8 void Input(const T& ); 9 10 // 删除队列的头结点 11 T Output(); 12 13 private: 14 queue<T> queue1; 15 queue<T> queue2; 16 };
1 template<typename T> void CStack<T>::Input(const T& t){ 2 if(queue1.empty()&&queue2.empty()) 3 queue1.push(t); 4 else 5 if(!queue1.empty()) 6 queue1.push(t); 7 else 8 queue2.push(t); 9 } 10 11 template<typename T> T CStack<T>::Output(){ 12 T t; 13 if(queue1.empty()&&queue2.empty()) 14 retutn NULL; 15 else 16 if(queue1.empty()){ 17 while(queue2.size()!=1){ 18 queue1.push(queue2.front()); 19 queue2.pop(); 20 } 21 t=queue2.front(); 22 queue2.pop(); 23 } 24 else 25 { 26 while(queue1.size()!=1){ 27 queue2.push(queue1.front()); 28 queue1.pop(); 29 } 30 t=queue1.front(); 31 queue1.pop(); 32 } 33 return t; 34 } 35