栈和队列的互相实现
来源:互联网 发布:软件设计方案评审 编辑:程序博客网 时间:2024/06/07 14:42
栈:先进后出,栈与调归密切相关;
队列:先进先出,队列在图(包括树)的宽度优先遍历中需要用到。
用两个栈实现一个队列:
我们通过一个具体的例子来分析往该队列插入和删除元素的过程(通过一个具体的例子来分析的方式通常能使问题变得很明朗,思路变得清晰。会在很大程度上简化问题)。首先插入一个元素a,不妨先把它插入到stack1,此时stack1中的元素有{a},stack2 为空。再压入两个元素b 和c,还是插入到stack1中,此时stack1中的元素有{a,b, c} ,其中c 位于栈顶,而stack2仍然是空的。这个时候我们试着从队列中删除一个元素。按照队列先入先出的规则,由于a 比b、c 先插入到队列中,最先被删除的元素应该是a。元素a 存储在stack1中,但并不在栈顶上,因此不能直接进行删除。注意到stack2我们还一直没有使用过,现在是让stack2发挥作用的时候了。如果我们把stack1中的元素逐个弹出并压入stack2, 元素在stack2中的顺序正好和原来在stack1中的顺序相反。因此经过3 次弹出stack1和压入stack2操作之后,stack1 为空, 而stack2中的元素是{c,b,a} ,这个时候就可以弹出stack2的栈顶a 了。此时的stack1为空,而stack2 的元素为{c,b},其中b 在栈顶。如果我们还想继续删除队列的头部应该怎么办呢?剩下的两个元素是b 和c。b 比c 早进入队列,因此b 应该先删除。而此时b 恰好又在栈顶,因此直接弹出stack2的栈顶元素即可。这次弹出操作之后,stack1中仍然为空,而stack2为{c} 。从上面的分析中我们可以总结出删除一个元素的步骤:
(1)当stack2 中不为空时, 在stack2中的栈顶元素是最先进入队列的元素, 可以弹出。
(2)如果stack2为空时,我们把stack1中的元素逐个弹出并压入stack2。
由于先进入队列的元素被压到stack1的底端,经过弹出和压入之后就处于stack2的顶端了, 又可以直接弹出。接下来再插入一个元素d。我们还是把它压入stack1 ,这样会不会有问题呢?我们考虑下一次删除队列的头部stack2不为空,直接弹出它的技顶元素c 。而c 的确是比d 先进入队列, 应该在d 之前从队列中删除, 因此不会出现任何矛盾。
template <typename T>class CQueue{public:CQueue(void);~CQueue(void);void AppendTail(T);T DeleteHead();private:stack<T> stack1;stack<T> stack2;};template <typename T> CQueue<T>::CQueue(void){}template <typename T> CQueue<T>::~CQueue(void){}template<typename T> void CQueue<T>::AppendTail(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 std::exception("queue is empty");T head=stack2.top();stack2.pop();return head;}int _tmain(int argc, _TCHAR* argv[]){CQueue<char> queue; queue.AppendTail('a'); queue.AppendTail('b'); queue.AppendTail('c'); char head = queue.DeleteHead(); system("pause"); return 0;}注意模板类的使用方式。一定要掌握通过具体的例子来分析问题的能力
用两个队列实现一个栈
我们通过一系列栈的压入和弹出操作来分析用两个队列模拟一个栈的过程。我们先往栈内压一个元素a。由于两个队列现在都是空的,我们可以选择把a 插入两个队列的任意一个。我们不妨把a插入queue1。接下来继续往栈内压入b 、c 两个元素,我们把它们都插入queue1。这个时候queue1包含3 个元素a 、b 和c,其中a 位于队列的头部,c 位于队列的尾部。现在我们考虑从栈内弹出一个元素。根据栈的后入先出原则,最后被压入战的c 应该最先被弹出。由于c 位于queue1的尾部,而我们每次只能从队列的头部删除元素,因此我们可以先从queue1中依次删除元素a、b并插入到queue2 中,再从queue1中删除元素c。这就相当于从栈中弹出元素c 了。我们可以用同样的方法从栈内弹出元素b 。接下来我们考虑往栈内压入一个元素d。此时queue1已经有一个元素,我们就把d 插入到queue1的尾部。如果我们再从栈内弹出一个元素,此时被弹出的应该是最后被压入的d。由于d 位于queue1的尾部,我们只能先从头删除queue1的元素井插入到queue2,直到在queue1中遇到d 再直接把它删除。
0 0
- 栈和队列的互相实现
- 栈和队列之间的互相实现
- Java队列和栈的互相转换
- 面试题7:栈和队列的互相实现(Leetcode-232和225)
- 栈与队列的互相转化
- 栈和队列的实现
- 栈和队列的实现
- 栈和队列的实现
- 栈和队列的实现
- 通过父子进程实现消息队列的互相通信
- 谈谈如何对栈和队列之间进行互相转换
- 队列实现栈和栈实现队列
- 栈和队列:栈的简单实现
- c++实现的循环队列和栈
- python栈和队列的实现
- 栈和队列的相互实现
- [算法拾遗]栈和队列的实现
- 栈和队列的基本操作实现
- c++ bitset 用法
- oracle sql语句如何检索出一个表的所有字段
- Java多线程编程
- POJ1611-The Suspects-ACM
- Python学习--文件和存储器的写入和读出实例
- 栈和队列的互相实现
- TRIZ理论的进化法则分析(TRIZ学习笔记)
- 数据统计(fopen版)
- lua的string库与强大的模式匹配
- Linux文件系统的实现
- 排序算法(四)-- 快速排序
- linux条件变量若干问题
- 远程备份脚本
- Flash+js幻灯片超炫的效果,值得一看