栈与队的互相实现

栈队列模拟:LeetCode中的数据结构应用,
文章探讨了如何使用栈和队列数据结构解决LeetCode中的232题(用栈实现队列)和225题(用队列实现栈),涉及push、pop、peek和empty操作的实现策略。

栈的特点是后进先出,队的特点是先进先出。今天我们学习的内容是用栈实现队和用队实现栈。

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

 一、LeetCode232.用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

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

说明:

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

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

思路:题目给了我们两个栈使用,我们一个用来存数据(push),另一个用来显示(peek)和弹出(pop)。当需要peek和pop的时候,就将栈一中的元素全部push到栈二当中。

所以代码中的 in2out()函数是关键~

画了图帮助理解

上代码

class MyQueue { // 定义一个名为MyQueue的类  
    Deque<Integer> inStack; // 定义一个Deque类型的成员变量inStack,用于存储进入队列的元素  
    Deque<Integer> outStack; // 定义一个Deque类型的成员变量outStack,用于存储从队列中取出的元素  
  
    public MyQueue() { // 定义MyQueue的构造函数  
        inStack = new LinkedList<Integer>(); // 使用LinkedList实现Deque,初始化inStack  
        outStack = new LinkedList<Integer>(); // 使用LinkedList实现Deque,初始化outStack  
    }  
  
    public void push(int x) { // 定义一个push方法,用于将元素x入队  
        inStack.push(x); // 将x添加到inStack的尾部  
    }  
  
    public int pop() { // 定义一个pop方法,用于取出队列中的元素  
        if (outStack.isEmpty()) { // 如果outStack为空,即队列中没有可取出的元素  
            in2out(); // 将inStack中的元素全部转移到outStack中,保证最先进入队列的元素在最前面  
        }  
        return outStack.pop(); // 返回并移除outStack的尾部元素,即队列中的第一个元素  
    }  
  
    public int peek() { // 定义一个peek方法,用于查看队列中的第一个元素但不取出  
        if (outStack.isEmpty()) { // 如果outStack为空,即队列中没有可查看的元素  
            in2out(); // 将inStack中的元素全部转移到outStack中,保证最先进入队列的元素在最前面  
        }  
        return outStack.peek(); // 返回并查看outStack的尾部元素,即队列中的第一个元素但不取出  
    }  
  
    public boolean empty() { // 定义一个empty方法,用于判断队列是否为空  
        return inStack.isEmpty() && outStack.isEmpty(); // 如果inStack和outStack都为空,则队列为空  
    }  
  
    private void in2out() { // 定义一个私有方法in2out,用于将inStack中的元素转移到outStack中  
        while (!inStack.isEmpty()) { // 当inStack不为空时  
            outStack.push(inStack.pop()); // 将inStack的元素弹出并添加到outStack中  
        }  
    }  
}

 二、LeetCode225.用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

思路:

入栈操作时,首先将元素入队到 queue2,然后将 queue1的全部元素依次出队并入队到queue2,此时 queue2的前端的元素即为新入栈的元素,再将 queue1和queue2互换,则 queue1的元素即为栈内的元素,queue 1的前端和后端分别对应栈顶和栈底。
由于每次入栈操作都确保queue1的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除queue1的前端元素并返回即可,获得栈顶元素操作只需要获得 queue 1的前端元素并返回即可(不移除元素)。
由于 queue 1用于存储栈内的元素,判断栈是否为空时,只需要判断 queue1是否为空即可。

画图理解

两个队列,都只能从上面出,下面入

代码如下

// 定义一个名为MyStack的类  
class MyStack {  
    // 声明两个队列,用于实现栈的操作。队列在Java中通常使用Queue接口和LinkedList实现。  
    Queue<Integer> queue1;  
    Queue<Integer> queue2;  
      
    // 定义构造函数,初始化两个队列  
    public MyStack() {  
        // 使用LinkedList实现Queue,初始化queue1  
        queue1 = new LinkedList<Integer>();  
        // 使用LinkedList实现Queue,初始化queue2  
        queue2 = new LinkedList<Integer>();  
    }  
      
    // 定义push方法,用于向栈中添加元素  
    public void push(int x) {  
        // 将元素x添加到queue2的尾部  
        queue2.offer(x);  
        // 只要queue1不为空,就将其中的元素全部移除并添加到queue2中  
        while (!queue1.isEmpty()) {  
            queue2.offer(queue1.poll());  
        }  
        // 临时交换queue1和queue2的引用,为了保持queue1始终是“空的”那个队列  
        Queue<Integer> temp = queue1;  
        queue1 = queue2;  
        queue2 = temp;  
    }  
  
    // 定义pop方法,用于从栈中取出并移除元素  
    public int pop() {  
        // 移除并返回queue1的第一个元素(栈顶元素)  
        return queue1.poll();  
    }  
      
    // 定义top方法,用于查看栈顶元素但不移除它  
    public int top() {  
        // 查看(但不移除)queue1的第一个元素(栈顶元素)  
        return queue1.peek();  
    }  
  
    // 定义empty方法,用于判断栈是否为空  
    public boolean empty() {  
        // 检查queue1是否为空,如果为空则返回true,否则返回false  
        return queue1.isEmpty();  
    }  
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值