首先定义两个队列分别为queue1和queue2。
1.大体思路:
队列实现栈,栈的特点是后进的先出,我们可以让元素入队queue1,留下队尾元素让其他元素出队,暂存到queue2中,然后让queue1中剩下的元素出队,即最后进的最先出来。
2.基本解决方案
按照上述的大体思路,我们给出解决方案:入栈和出栈都在queue1中完成,queue2只作为临时中转空间。
入栈 入队queue1
出栈 除queue1队尾的元素外将其他所有元素出队queue1,再入队queue2(中转暂存),然后将queue1中的元素出队(出栈)。最后一步,将暂存在queue2中的元素再倒回queue1中。
为描述清晰,请看下图:
事实上,这个思路和用两个栈实现队列的方案1类似,都是第二个数据区作为暂存中转,最后在倒回到第一个数据区。
3.改进后的方案
上述方案是一个基本的最容易想到的解决方案,但是仔细观察会发现其并不完美:在每次出栈步骤中要把queue2中的元素倒回到queue1中,这个操作很累赘,能否优化一下,可不可以不用每次先出栈后倒回??下面给出改进后的方案
入栈:
两个队列全空:任选一个队列让元素入队,此处规定queue1
两个队列一个空:让元素入队非空的队列
注:不考虑两个队列全满,因为本身没意义
出栈: 将非空队列中除最后入队的元素之外的其他所有元素入队到另外一个队列中,然后出队剩下的那个元素(后进来的先出去,完成出栈)
相比于基本方案,改进后的方案没有了基本方案中的倒回操作,整个流程变得简洁高效,下面给出改进方案的java代码实现。
4.java代码实现
public class Queues2Stack { private ArrayQueue q1; private ArrayQueue q2; private int maxLength; public Queues2Stack(int capacity){ maxLength = capacity; q1 = new ArrayQueue(capacity); q2 = new ArrayQueue(capacity); } public int getSize(){ return q1.getsize()+q2.getsize(); } /** * 入栈: * @param element 入栈元素 * @return 入栈成功结果? */ public boolean push(int element){ if(getSize() == maxLength){ //队列都满,此情景无意义 return false; } if(q2.isEmpty()){ q1.put(element); }else{ q2.put(element); } return true; } /** * 出栈 * @return 出栈元素 */ public Object pop(){ if(getSize()==0){ throw new IndexOutOfBoundsException("空栈,无元素可出栈"); }else{ //留非空队列中最后一个元素,其他搬到空队列中 if(q2.isEmpty()){ while(q1.getsize()>1) q2.put(q1.pull()); return q1.pull(); //出队最后一个,实现后进先出 }else{ while(q2.getsize()>1) q1.put(q2.pull()); return q2.pull(); //出队最后一个,实现后进先出 } } } }
测试程序:
public class Queues2StackTest { public static void main(String[] args) { Queues2Stack s = new Queues2Stack(5); s.push(1); s.push(2); s.push(3); System.out.println(s.pop()); //返回3 s.push(4); s.push(5); System.out.println(s.pop()); //返回5 System.out.println(s.pop()); //返回4 System.out.println(s.pop()); //返回2 System.out.println(s.pop()); //返回1 System.out.println(s.pop()); //抛出异常:提示栈为空 } }
0条评论
点击登录参与评论