zoukankan      html  css  js  c++  java
  • 两个栈实现一个队列,两个队列实现一个栈

    题目:用两个栈实现一个队列,用两个队列实现一个栈。

    首先要了解栈和队列这两种数据结构各自的特点,栈是一种后入先出(Last In First Out,LIFO)的数据结构,队列是一种先进先出(First In First Out,FIFO)的数据结构。

    1. 两个栈实现一个队列

    两个栈实现一个队列有如下两种解决思路。

    思路一:s1是入栈的,s2是出栈的。

    (1)入队列,直接压到s1中去就行了。

    (2)出队列,先把s1中的元素全部出栈压入s2中,弹出s2中的栈顶元素,再把s2的所有元素全部压回s1中。

    思路一方案实现过程

     

    我们发现,栈s1负责元素的存储,栈s2作为过渡栈,每次元素出队时都需要将元素倒入到栈s2,弹出元素后又将元素倒回到栈s1,可以看出这个过程比较麻烦,因此有了如下思路二。

     

    思路二:s1是入栈的,s2是出栈的。

    (1)入队列:直接压入s1即可。

    (2)出队列:如果s2不为空,把s2中栈顶元素直接弹出;否则,把s1的所有元素全部弹出压入s2中,再弹出s2的栈顶元素。

     

    元素出队列有两种情况,一种是s1栈不为空,栈s2为空,此时将s1中元素都倒入s2,弹出栈s2的栈顶元素;一种是s1和s2都不为空,此时直接弹出栈s2的栈顶元素。

     

    出队情况一:栈s1不为空,栈s2为空。

    情况一元素出队列过程

     出队情况二 :栈s1和s2都不为空。

    情况二元素出队列过程

    相比思路一,思路二的方案减少了元素在两个栈内的转移,显然是一种比较优化的方案。 思路二的实现代码如下:

     1 import java.util.Stack;
     2 
     3 public class b09_用两个栈实现队列 {
     4     
     5     public static void main(String[] args) {
     6         QueueWithTwoStack queue = new QueueWithTwoStack();
     7         queue.offer(1);
     8         queue.offer(2);
     9         queue.offer(3);
    10         System.out.println(queue.peek());
    11         System.out.println(queue.poll());
    12         System.out.println(queue.peek());
    13     }
    14     
    15     private static class QueueWithTwoStack{
    16         
    17         public static Stack<Integer> stackPush;        //只负责入栈
    18         public static Stack<Integer> stackPop;        //只负责出栈
    19         
    20         public QueueWithTwoStack() {
    21             stackPush = new Stack<>();
    22             stackPop  = new Stack<>();
    23         }
    24         
    25         /*
    26          * 在队列尾部插入结点
    27          */
    28         public void offer(int data) {
    29             // 元素直接入栈
    30             stackPush.push(data);
    31         }
    32         
    33         /*
    34          * 在队列头部删除结点
    35          */
    36         public int poll() {
    37             if (stackPop.empty() && stackPush.empty()) {    //两个栈都为空
    38                 throw new RuntimeException("Queue is empty.");
    39             } else if (stackPop.empty()) {
    40                 // stackPop为空,则将stackPush中的元素倒入stackPop
    41                 while(!stackPush.empty()){
    42                     stackPop.push(stackPush.pop());
    43                 }
    44             }
    45             return stackPop.pop();
    46         }
    47         
    48         /*
    49          * 取队列头部结点,不从队列中移除结点
    50          */
    51         public int peek() {
    52             if (stackPop.empty() && stackPush.empty()) {
    53                 throw new RuntimeException("Queue is empty!");
    54             } else if (stackPop.empty()) {        // 用于出栈的栈为空
    55                 while (!stackPush.empty()) {
    56                     stackPop.push(stackPush.pop());
    57                 }
    58             }
    59             // 用于出栈的栈不为空则直接去栈顶元素
    60             return stackPop.peek();
    61         }
    62     }
    63 }

    2. 两个队列实现一个栈

     思路一:q1是专职进出栈的,q2只是个中转站。

    1)入栈:直接入队列q1即可;

    2)出栈:把q1的除最后一个元素外全部转移到队q2中,然后把刚才剩下q1中的那个元素出队列。之后把q2中的全部元素转移回q1中。

    元素入栈出栈过程

    思路二:q1q2同时负责进出栈。

    1)入栈:如果q1q2都为空,则随便入哪个队列都可;如果一个队列为空一个队列非空,则元素入非空队列;如果两个都非空,则入队列q1即可;

    2)出栈:如果一个队列为空一个队列非空,则将非空队列的队尾元素出队;如果两个队列都非空,则将队列q1的队尾元素出队,其他元素入队列q2

     

    其实思路二和前面两个栈实现一个队列的思路类似,都是减少元素在两个队列之间的转换,都是一种优化的解决方案。思路二的代码实现如下:

     1 import java.util.LinkedList;
     2 
     3 public class b09_用两个队列实现栈 {
     4 
     5     public static void main(String[] args) {
     6         StackWithTwoQueue stack = new StackWithTwoQueue();
     7         stack.push(1);
     8         stack.push(2);
     9         stack.push(3);
    10         
    11         System.out.println(stack.peek());
    12         stack.push(4);
    13         System.out.println(stack.pop());
    14         System.out.println(stack.pop());
    15     }
    16 
    17     public static class StackWithTwoQueue {
    18         static LinkedList<Integer> queue1 = new LinkedList<>();
    19         static LinkedList<Integer> queue2 = new LinkedList<>();
    20         
    21         /*
    22          * 向栈中添加元素
    23          */
    24         public static void push(int data) {
    25             if (!queue1.isEmpty()) {
    26                 queue1.offer(data);
    27             } else {
    28                 queue2.offer(data);
    29             }
    30         }
    31         
    32         /*
    33          * 从栈中取出栈顶元素
    34          */
    35         public static int pop() {
    36             if (!queue1.isEmpty()) {
    37                 // queue1不为空,则把queue1中除最后一个元素的其他元素移入queue2
    38                 while(queue1.size() != 1) {
    39                     queue2.offer(queue1.poll());
    40                 }
    41                 return queue1.poll();
    42             } else if (!queue2.isEmpty()) {
    43                 // queue2不为空,则把queue2中除最后一个元素的其他元素移入queue1
    44                 while(queue2.size() != 1) {
    45                     queue1.offer(queue2.poll());
    46                 }
    47                 return queue2.poll();
    48             } else {
    49                 System.out.println("Stack is empty!");
    50             }
    51             return -1;
    52         }
    53         
    54         /*
    55          * 取栈顶元素
    56          */
    57         public static int peek() {
    58             if (!queue1.isEmpty()) {
    59                 while (queue1.size() != 1) {
    60                     queue2.offer(queue1.poll());
    61                 }
    62                 // 和pop()函数思路一样,只是最后一个元素取出后需要将该元素再添加到queue2中
    63                 int val = queue1.poll();
    64                 queue2.offer(val);
    65                 return val;
    66             } else if (!queue2.isEmpty()) {
    67                 while(queue2.size() != 1) {
    68                     queue1.offer(queue2.poll());
    69                 }
    70                 int val = queue2.poll();
    71                 queue1.offer(val);
    72                 return val;
    73             } else {
    74                 System.out.println("Stack is empty!");
    75             }
    76             return -1;
    77         }
    78     }
    79 }

     相比思路一,思路二的方案减少了元素在两个栈内的转移,显然是一种比较优化的方案。

  • 相关阅读:
    Python推导式(Comprehension)
    mysql中文乱码
    入门学习hibernate
    什么是ORM?
    Java网站中的权限管理
    Java的8中基本数据类型
    Python获取文件夹大小
    Python技巧
    Python中取整的方法floor,ceil,round
    Python线程join和setDaemon
  • 原文地址:https://www.cnblogs.com/lemonu/p/8877878.html
Copyright © 2011-2022 走看看