数据结构 Java数据结构 --- 栈和队列_平台将创建用户补全后的mystack类的对象; 调用对象的push(t item)方法,添加数据;(1)

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

在这里插入图片描述

2.2 实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
在这里插入图片描述

public class MyQueueByLinkedList {
    /\*\*
 \* Node这个类叫做"内部类",定义在某个类或者方法中的类
 \* static 效果就是: 创建Node的实例不依赖 MyQueueByLinkedList 这个类的实例
 \*/
    static class Node{
        public int val;
        Node next = null;

        public Node(int val){
            this.val = val;
        }
    }

    // 创建一个链表,就得有头节点.此处的head节点不是傀儡节点.
    // 基于链表来实现队列,可以入队列可以从尾巴插入,出队列从头部删除;
    // 也可以入队列从头部插入,出队列从尾部删除
    // 无论是那种实现方式,最好都把头和尾都记录下来.
    private Node head = null;
    private Node tail = null;

    // 入队列(标准库的队列,入队列操作就叫 offer)
    public void offer(int val) {
        Node newNode = new Node(val);
        if(head == null){
            head = newNode;
            tail = newNode;
            return;
        }
        //如果非空
        tail.next = newNode;
        tail = newNode;
    }

    // 出队列
    public Integer poll(){
        // 如果当前队列就是空队列,再去poll显然不科学
        if(head == null){
            // 如果出队列失败,返回一个错误的值
            return null;
        }
        int ret = head.val;
        head = head.next;
        if(head == null){
            //删除当前元素之后,队列变成了空的队列
            tail = null;

        }
        return ret;
    }

    // 取队首的元素
    public Integer peek() {
        if(head == null){
            return null;
        }
        return head.val;
    }
}


2.3 循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。
环形队列通常使用数组实现。
在这里插入图片描述

public class MyQueueByArray {
    private int[] elem = new int[100];
    // [head,tail) 有效元素的范围. 注意, tail 可能在 head 之前
    private int head = 0; // 表示对首元素下标
    private int tail = 0; // 表示对尾下一个元素的下标
    private int size = 0; // 元素个数

    public void offer(int val){
        if (size == elem.length) {
            //队列满了, 无法继续插入
            return ;
        }
        // 保证这个操作下标不能越界
        elem[tail] = val;
        tail++;
        // tail ++ 之后如果超出数组有效范围,就从头开始
        if (tail >= elem.length){
            tail = 0;
        }
        size++;
    }

    public Integer poll(){
        if (size == 0){
            return null;
        }
        Integer ret = elem[head];
        head++;
        if(head >= elem.length){
            head = 0;
        }
        size--;
        return ret ;
    }

    public Integer peek(){
        if(size == 0){
            return null;
        }
        return elem[head];
    }
}


3. 双端队列 (Deque)

3.1 概念

双端队列(deque) 是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。
那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

4. java 中的栈和队列

Stack

方法解释
E push(E item)压栈
E pop()出栈
E peek()查看栈顶元素
boolean empty()判断栈是否为空
Stack方法的演示:
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        //压栈
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        //查看栈顶元素
        System.out.println(stack.peek());

        //出栈
        int ret = stack.pop();
        System.out.println(ret);  //4
        ret = stack.pop();
        System.out.println(ret);  //3
        ret = stack.pop();
        System.out.println(ret);  //2
        ret = stack.pop();
        System.out.println(ret);  //1
        //判断栈是否为空
        System.out.println(stack.empty());
        //此时栈为空 如果 查看栈顶元素 或者 出栈 会报异常(EmptyStackException)
        System.out.println(stack.peek());
        System.out.println(stack.pop());
    }

运行结果:
在这里插入图片描述

Queue

错误处理抛出异常返回特殊值
入队列add(e)offer(e)
出队列remove()poll()
队首元素element()peek()

Deque

头部/尾部头部元素(队首)尾部元素(队尾)
错误处理抛出异常返回特殊值
入队列addFirst(e)offerFirst(e)
出队列removeFirst()pollFirst()
获取元素getFirst()peekFirst()

总结:
Stack:
push ,pop,peek.当当前是一个空栈的,再去pop或者peek就会产生异常.
Queue:
add,remove,element 如果当前操作失败就会抛出异常;
offer,poll,peek 如果操作失败就会返回一个错误值;

5. LeetCode 题目

第一题 : 有效的括号

有效的括号
LeetCode 20:
描述:
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
解题思路:

1. 遍历字符串,依次取出字符串中的字符.
      1.1 如果取出的字符串为左括号例如’(‘,’[‘,’{‘.就放入栈中
      1.2 如果取出的字符串为右括号例如’)‘,’]‘,’}'.就和栈顶元素比较是否匹配.
            a) 匹配就出栈,然后继续遍历.
            b) 不匹配就直接返回false
      1.3 如果栈为空,且取出的字符是右括号,则返回false没有例如字符串"]()"
2. 遍历结束后,判断是否栈为空
      2.1 如果为空 则满足题意 return true;
      2.2 如果不为空 表示没有足够匹配的字符, return false; 如字符串"["

画图解析:

在这里插入图片描述
在这里插入图片描述

代码实现:
    public boolean isValid(String str) {
        Map<Character,Character> map = new HashMap<>();
        map.put('(',')');
        map.put('[',']');
        map.put('{','}');

        //1.先创建一个栈,栈中保存字符类型即可
        Stack<Character> stack = new Stack<>();
        //2.遍历字符串的每个字符
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            //3.判断字符 ch 是否为左括号,如果是,就入栈
            if (ch == '(' || ch == '[' || ch == '{'){
                stack.push(ch);
                continue;//进入下次循环,取出下一个字符
            }
            if(stack.empty()){
                //如果ch不是左括号,且栈为空,则不是合法括号
                return false;
            }
            //4.判断ch是否是右括号,如果是,就取栈顶元素比较是否相等
            char top = stack.pop();//栈顶元素
            //以下是3种情况合法情况 -- 写法1
            /\*if(top == '(' && ch == ')') {
 continue;
 }
 if(top == '[' && ch == ']') {
 continue;
 }
 if(top == '{' && ch == '}') {
 continue;
 }\*/
            // 判断合法情况 -- 写法2
            if(map.get(top) == ch){
                continue;
            }
            //如果三种情况都不满足,表示不是合法情况
            return false;
        }
        //遍历完成后 如果栈为空 则满足条件
        if(stack.empty()) {
            return true;
        }
        //否则就不合法
        return false;
    }

第二题 : 用队列实现栈

用队列实现栈
LeetCode 225:
描述:
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:

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

注意:

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

1. 用两个队列来模拟一个栈的效果,引用两个队列 A 和 B .
2. 入栈 : 直接把元素入队到A中即可
3. 出栈 : 因为队列是先进先出的,栈是后进先出的,可以让 A队列 元素出队列然后入队列到 B队列 中,直到A队列中最后一个元素的时候,直接出队列,就实现了后进先出.然后要让A和B交换,始终让入栈到A队列中.
4. 取栈顶元素 : 取栈顶元素就是 出栈 的元素, 不过取栈顶元素要把这个元素返回去
5. 判断是否为空 : A 和 B都为空的时候 就是空栈

画图解析:

1NETiBAd3d6enp6enp6enp6enp6,size_20,color_FFFFFF,t_70,g_se,x_16)

代码实现:
import java.util.LinkedList;
import java.util.Queue;

public class MyStackByDoubleQueue {
    private Queue<Integer> A = new LinkedList<>();
    private Queue<Integer> B = new LinkedList<>();

    public void push(int x) {
        // x往A中入队列即可
        A.offer(x);
    }

    public Integer pop() {
        if (empty()){
            return null;
        }
        // 把A中的元素往 B 中放
        while(A.size() > 1) {
            Integer font = A.poll();
            B.offer(font);
        }
        //当循环结束后,A 中 应该只剩1个元素
        //这个元素就应该是被出栈的元素
        int ret = A.poll();
        //交换A和B
        swapAB();
        return ret;
    }

    private void swapAB(){
        Queue<Integer> tmp = A;
        A = B;
        B = tmp;
    }

    public Integer top() {
        if (empty()){
            return null;
        }
        // 把A中的元素往 B 中放
        while(A.size() > 1) {
            Integer font = A.poll();
            B.offer(font);
        }
        //当循环结束后,A 中 应该只剩1个元素
        //这个元素就应该是被出栈的元素
        int ret = A.poll();
        B.offer(ret); // top 和 pop的区别就是 top要把元素返回去,pop不需要返回去
        //交换A和B
        swapAB();
        return ret;
    }

    public boolean empty() {
        return A.isEmpty() && B.isEmpty();
    }
}

第三题 : 用栈实现队列

用栈实现队列
LeetCode 232:
描述:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:

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

1. 引用2个栈A和B,A专门用来入队列;B专门用来出队列
2. 实现入队列: 先把B中的所有元素都放到A中(因为出栈的时候元素会放入B中),然后直接往A里入栈.
3. 实现出队列: 后进先出的栈实现先进先出的队列,要让A中的所有元素移入B中,先出的的元素就是后进的,此时栈顶就是就是最先进入的元素,B中出栈操作即可
4. 实现取队首元素: 同出队列操作,把A所有元素放入B中,然后取B的栈顶元素就是队首元素.
5. 判空: A 和 B 都为空.

画图解析:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

代码实现:
import java.util.Stack;

public class MyQueueByDoubleStack {
    private Stack<Integer> A = new Stack<>();
    private Stack<Integer> B = new Stack<>();

    public void push(int x) {
        //1.先将B中的元素 放入 A 中
        while (!B.isEmpty()){
            int tmp = B.pop();
            A.push(tmp);
        }
        //2.把新元素放入A中
        A.push(x);
    }


    public Integer pop() {
        //1.如果为空 直接返回
        if(empty()){
            return null;
        }
        //2.把A中的元素都给B
        while(!A.isEmpty()){
            int tmp = A.pop();
            B.push(tmp);
        }
        //3.针对B进行出栈
        return B.pop();
    }

    public Integer peek() {
        //1.如果为空 直接返回
        if(empty()){
            return null;
        }
        //2.把A中的元素都给B
        while(!A.isEmpty()){
            int tmp = A.pop();
            B.push(tmp);
        }
        //3.取B的栈顶元素
        return B.peek();
    }

    public boolean empty() {
        return A.isEmpty() && B.isEmpty();
    }
}


第四题 : 最小栈

最小栈
LeetCode 155:
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

  • push(x) —— 将元素 x 推入栈中。
  • pop() —— 删除栈顶的元素。
  • top() —— 获取栈顶元素。
  • getMin() —— 检索栈中的最小元素。
解题思路:

1. 引用2个栈A和B, A按照正常栈的规则入栈出栈,B存放的是A的最小值以及A历史的最小值
2. 实现入栈操作: A中: 直接入栈 . B中: 取要入栈的值 和 B栈顶元素比较,把较小值入栈到B中.
3. 实现出栈操作: A 和 B 一起出栈
4. 实现取栈顶元素操作: 直接取 A 栈顶元素
5. 实现取最小值操作: 直接取 B 栈顶元素

画图解析:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码实现:
import java.util.Stack;

public class MinStack {
    private Stack<Integer> A = new Stack<>();
    private Stack<Integer> B = new Stack<>();

    public void push(int x){
        //A 直接入栈
        A.push(x);
        //如果B为空 直接入栈
        if(B.isEmpty()){


![img](https://img-blog.csdnimg.cn/img_convert/538b1f185717093187dd7d81ab9788f7.png)
![img](https://img-blog.csdnimg.cn/img_convert/cb6d83c4325920faab02e0f24d817138.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

t_70,g_se,x_16)


#### 代码实现:



import java.util.Stack;

public class MinStack {
private Stack A = new Stack<>();
private Stack B = new Stack<>();

public void push(int x){
    //A 直接入栈
    A.push(x);
    //如果B为空 直接入栈
    if(B.isEmpty()){

[外链图片转存中…(img-LniNAZBR-1715809172615)]
[外链图片转存中…(img-KedVFwD3-1715809172615)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值