栈和队列相互实现(Java)

本篇任务

前篇我们分别介绍了栈和队列,并对其进行了简单的自我实现,本篇我们将通过栈和队列的相互实现来进一步熟悉和运用栈和队列,如下是我们将要完成的题目:

用队列实现栈icon-default.png?t=O83Ahttps://leetcode-cn.com/problems/implement-stack-using-queues/

用栈实现队列icon-default.png?t=O83Ahttps://leetcode-cn.com/problems/implement-queue-using-stacks/

问题描述

  实现 MyQueue 类和 MyStack 类::

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

  说明:

  • 你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

     不论是用队列模拟栈,还是用栈模拟队列,我们都会发现使用 poll 方法取出元素时,栈 Stack 从顶部取出即 34 ,而队列则从队头取出 12

原因分析:

        使用一个栈来模拟队列时,所有元素都会被推入栈中,这意味着后入栈的元素会先出栈,与队列的先进先出特性不符。使用一个队列模拟栈时情况于此相反。那么如何解决这个问题呢?。


解决方案:


        为了实现队列的先进先出(FIFO)特性,我们通常会使用两个栈来模拟队列。一个栈用于入队操作,将元素按顺序推入栈中。另一个栈用于出队操作,当需要出队时,将入队栈中的元素依次弹出并推入出队栈中,然后从出队栈中弹出元素即可实现队列的先进先出特性。

        创建两个栈,Queue1 和 Queue2 ,向栈中添加元素时,同样向 Queue1 中添加,当模拟出栈操作时,将 Queue1 队列中除了最后一个元素之外的所有元素,逐个出队并入队到 Queue2 队列中。然后将 Queue1 队列中的最后一个元素出队,即为栈Q顶元素。

    其余操作依次类推,将数据不断在 Queue1 和 Queue2 中转换即可,代码实现如下: 

public class MyStackByQueue {
        public Queue<Integer> que1;
        public Queue<Integer> que2;
        public MyStackByQueue() {
            que1=new LinkedList<>();
            que2=new LinkedList<>();
        }

        public void push(int x) {
            if(!que1.isEmpty()) {
                que1.offer(x);
            }else if(!que2.isEmpty()) {
                que2.offer(x);
            }else {
                que1.offer(x);
            }
        }

        public int pop() {
            if(empty()){
                return -1;
            }
            if(!que1.isEmpty()){
                int size= que1.size()-1;
                for(int i=0;i<size;i++){
                    que2.offer(que1.poll());
                }
                return que1.poll();
            }else{
                int size=que2.size()-1;
                for(int i=0;i<size;i++){
                    que1.offer(que2.poll());
                }
                return que2.poll();
            }
        }

        public int top() {
            int val=0;
            if(empty()){
                return -1;
            }
            if(!que1.isEmpty()){
                int size=que1.size();
                for(int i=0;i<size;i++){
                    val=que1.poll();
                    que2.offer(val);
                }
                return val;
            }else{
                int size= que2.size();
                for(int i=0;i<size;i++){
                    val=que2.poll();
                    que1.offer(val);
                }
                return val;
            }
        }

        public boolean empty() {
            return que1.isEmpty()&&que2.isEmpty();
        }
    }

        为了满足栈的后进先出(FOFI)Q的特性,通常使用两个队列实现栈Q。入栈操作时,将元素添加到非空的队列末尾;出栈操作时,将非空队列中的元素逐个取出并加入空队列,直到取出待出栈元素,然后将非空队列和空队列的角色互换,以便下一次操作。这样就可以实现栈的后进先出的效果

        定义两个链栈Stack1和Stack2,其中Stack1用于入队操作,Stack2用于出队操作。入队操作时,直接将元素压入Stack1即可。出队操作时,首先判断Stack2是否为空。若不为空,则直接弹出Stack2的栈顶元素即为出队元素;若为空,则将Stack1中的所有元素逐个弹出并压入Stack2,然后弹出Stack2的栈顶元素。

  代码实现如下: ( top() 换为 peek()

public class MyQueueByStack {
    public Deque<Integer> st1;
    public Deque<Integer> st2;
    public MyQueueByStack() {
        st1=new LinkedList<>();
        st2=new LinkedList<>();
    }

    public void push(int x) {
        st1.offer(x);
    }

    public int pop() {
        if(empty()){
            return -1;
        }
        if(!st1.isEmpty()){
            int size=st1.size();
            for(int i=0;i<size;i++){
                st2.offer(st1.poll());
            }
        }
        return st2.poll();
    }

    public int peek() {
        if(empty()){
            return -1;
        }
        if(!st1.isEmpty()){
            int size=st1.size();
            for(int i=0;i<size;i++){
                st2.offer(st1.poll());
            }
        }
        return st2.peek();
    }

    public boolean empty() {
        return st1.isEmpty()&&st2.isEmpty();
    }
}

      到这里本篇就圆满完成!有问题或不懂之处欢迎在评论区提出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值