代码随想录算法训练营第10天| | 栈和队列理论基础 | | 232.用栈实现队列 | | 225.用队列实现栈

文章讨论了Java中栈和队列的数据结构,包括它们的基础理论和实现方式。栈是Vector的子类,具有线程安全性但效率较低;队列Queue通常由LinkedList实现。文章通过232题和225题举例说明如何使用栈实现队列以及队列实现栈,提供了两种不同的实现策略,并强调了代码优化的重要性。
摘要由CSDN通过智能技术生成

代码随想录算法训练营第10天| | 栈和队列理论基础 | | 232.用栈实现队列 | | 225.用队列实现栈

栈和队列理论基础

Java中的栈

  • 栈是Vector的一个子类,实现标准的后进先出的栈,这也意味着Stack的底层实现和Vector类似,扩容机制也一样
  • Stack同Vector一样,在方法上添加了synchronized,达到线程安全的目的,但是这特别消耗资源,不推荐使用

Java中的队列

  • Queue是个接口,设计了基础方法,具体实现代码取决于实现类
  • Queue的常见底层实现为LinkList,底层链表实现

双向队列Deque(较为常用,同时具有栈和队列的功能)

  • 继承Queue,且增加反向序列的方法
  • 支持尾部插入,头部插入,尾部弹出,头部弹出等,参考网址

232.用栈实现队列

使用栈(只能使用几个基本操作)实现队列的下列操作:

push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。

个人思路:

  • 因为栈的顺序是先进先出,所以一放一出顺序就正常了
  • 这里我们只要设计两个栈,一个用于存入,另一个用于弹出,只有当弹出栈为空,才将存入栈弹到弹出栈保存,放在顺序混乱
class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    public MyQueue() {
        stackIn = new Stack<>();
        stackOut = new Stack<>();
    }

    public void push(int x) {
        stackIn.push(x);
        if (stackOut.empty()) {
            while (!stackIn.empty()) {
                stackOut.push(stackIn.pop());
            }
        }
    }

    public int pop() {
        if (stackOut.empty()) {
            while (!stackIn.empty()) {
                stackOut.push(stackIn.pop());
            }
        }
        return stackOut.pop();
    }

    public int peek() {
        if (stackOut.empty()) {
            while (!stackIn.empty()) {
                stackOut.push(stackIn.pop());
            }
        }
        return stackOut.peek();
    }

    public boolean empty() {
        return stackOut.empty() && stackIn.empty();
    }
}

题解解析:(和上述办法差不多)

  • 需要一个输入栈和一个输出栈
  • pop操作时,输出栈如果为空,就要把进栈数据全导过来(注意是全部导入)
  • 如果两个栈都为null,则队列为null
  • 注意相近的代码要抽象出来,不要大量的复制粘贴,很容易出问题,上述代码就存在这个问题
//改进代码
class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    public MyQueue() {
        stackIn = new Stack<>();
        stackOut = new Stack<>();
    }

    public void push(int x) {
        stackIn.push(x);
    }

    public int pop() {
        dumpstackIn();
        return stackOut.pop();
    }

    public int peek() {
        dumpstackIn();
        return stackOut.peek();
    }

    public boolean empty() {
        return stackOut.empty() && stackIn.empty();
    }

    //注意此处是私有方法,不暴露给外部
    private void dumpstackIn() {
        if (!stackOut.isEmpty()) return;
        while (!stackIn.isEmpty()) {
            stackOut.push(stackIn.pop());
        }
    }
}

225.用队列实现栈

使用队列实现栈的下列操作:

  • push(x) – 元素 x 入栈
  • pop() – 移除栈顶元素
  • top() – 获取栈顶元素
  • empty() – 返回栈是否为空

个人思路:

  • 法一:使用两个队列
    • 一个队列用于输入元素,另一个队列在获取元素时作为临时存放站
    • 每次获取元素时,都要将数据从一个队列全部存放到另一个队列,然后输出最后一个或弹出最后一个
class MyStack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;

    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }

    public void push(int x) {
        queue1.add(x);
    }

    public int pop() {
        if (queue1.isEmpty())
            return -1;
        while (queue1.size() != 1) {
            queue2.add(queue1.poll());
        }
        Integer poll = queue1.poll();
        queue1 = queue2;
        queue2 = new PriorityQueue<>();
        return poll;
    }

    public int top() {
        Integer poll = pop();
        queue1.add(poll);
        return poll;
    }

    public boolean empty() {
        return queue1.isEmpty();
    }
}
  • 法二:使用一个队列
    • 当需要弹出或获取栈顶元素时,只需要一边弹出一边存入即可,循环n-1次即可
class MyStack {
    Queue<Integer> queue;

    public MyStack() {
        queue = new LinkedList<>();
    }

    public void push(int x) {
        queue.add(x);
    }

    public int pop() {
        if (queue.isEmpty())
            return -1;
        for (int i = 0; i < queue.size() - 1; i++) {
            queue.add(queue.poll());
        }
        return queue.poll();
    }

    public int top() {
        Integer poll = pop();
        queue.add(poll);
        return poll;
    }

    public boolean empty() {
        return queue.isEmpty();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值