您的位置:首页 > 其它

两个栈模拟一个队列

2015-09-23 23:05 183 查看

两个栈模拟一个队列

毕业后进入第一家公司其中有一道面试题就是用两个队列模拟一个栈,自己在面试中也喜欢出这道题。最近又看到了这个问题,做个总结吧,先谈谈比它略简单一些的用两个栈模拟一个队列。
一,解法
这个问题一般的人都会有想法,如果面试中遇到想不到的人直接pass应该没什么问题。大家都明白一个道理,负负得正,两次先进后出正好相当于一次先进先出。有了这个思路,几乎就已经解出了这道题。
假设我们有两个容量都为n的栈stack1和stack2。入队的操作可以是这样:查看stack1是否已满,未满则直接入栈;若stack1已满且stack2为空,则将stack1中的元素转移到stack2中;如果发现stack1满了并且stack2不为空,此时已经不能再继续入栈了,否则最后插入元素到stack1中。
出队的操作是这样的:查看stack2中是否有元素,若有则直接出栈;若stack2为空且stack1不为空,同样将stack1中的元素转移到stack2;如果两个stack都是空的,说明整个队列是空的,否则最后在stack2中出栈。
当然,这只是其中的一种解法,主要的地方是要坚持下面的原则。stack2作为出队的操作栈,从栈顶到栈底的元素即是按出队顺序排好的元素。若stack2中已经有元素,则不能再向stack2中添加,否则会在准备出队的元素前面添加上其他元素。
二,性能分析与改进
根据上面的步骤可以得出,这个队列的最大容量是2n,即两个栈的容量和。最坏情况下,队列的容量是什么呢?考虑这样一个情况,stack1中刚有两个元素的时候,来个一个出队请求,这时候stack1中的元素转移到stack2中,然后对stack2进行一次出栈,stack1变为空栈,stack2中有一个元素。但是,此时stack2中已经有了元素,已经不能把stack1中的元素再转到stack2中了。所以此时再进行多次入队直到stack1变满,就已经不能再入队了,这个时候的队列容量是n+1。
看懂的人可能会想到,你傻呀,再把stack2中的元素转回来不就可以了。是的,可以针对在stack1未满时进行出队操作进行改造。如果在出队时发现stack2为空且stack1未满,则将stack1中的元素都转到stack2中,执行完出队操作后再将stack2中的元素转回到stack1中,等到stack1变满时在转到stack2中。这样就会到达一个效果,stack1满后才会被迫将元素真正转到stack2中,而转移元素后,stack1又可以作为一个空栈接收n个新元素。举个例子,12345入队到stack1中,现在需要出队,则12345转到stack2中为54321,1出队后stack2中还剩5432,转回到stack1中为2345。这种情况有一个缺点,如果队列经常在stack1未满的时候出队,它的效率会变低,因为原来从stack1到stack2只转了一次,现在要来回转三次。
如果两个栈的容量不一样呢?这时候怎么办呢?假设两个栈的容量分别为n1、n2。可以让容量比较大的作为入队的栈stack1。在入队时如果发现stack1的元素数目已经到了n2,而且此时stack2正好为空,则将stack1中的元素全部转到stack2中。为什么要这样呢,上文中提到一条原则,stack2不为空的时候是不能互相转数据,这个时候相当于锁定了n2的容量,所以我们选择容量较小的栈作为出队的操作栈stack2。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: