当前位置: 首页 > article >正文

JAVA_数据结构_栈和队列

1.栈(Stack)

1.1概念

        是一种特殊的线性表,它只允许一端进行增删查改操作,它的头称为栈顶,进行压栈和出栈的操作,则另一端称为栈底,并且它遵循着先进后出的操作。

        压栈:也可称为进栈/入栈,该功能为为栈添加数据,在栈顶操作。

        出栈:该功能为栈删除数据,在栈顶操作。

        先进后出:也可称为后进先出,相当于几个人进到一个细小的胡同里,里面只能一人并排走,则第一人进去后,第二个第三个依次进去,可这是个胡同,前面无路可走,要想出去就只能让最后一个人进来的人先出去,而最先进来的人是最后一个出去的,这就是先进后出/后进先出

        

1.2栈的使用

  1. Stack:创建一个空的栈
  2. E push(E e):为一个栈添加元素
  3. E peek():取得栈顶元素不删除
  4. E pop():取得栈顶元素并删除
  5. int size():取得栈中的元素个数
  6. boolean isEmpty():判断栈是否为空 是为true 不是为false

public static void main(String[] args) {
        //1.创建栈
        Stack<Integer> stack=new Stack<>();
        //2.为栈添加元素
        stack.push(1);
        stack.push(1);
        stack.push(1);
        //3.取得栈顶元素 不删除
        stack.peek();
        //4.取得栈顶元素并删除
        stack.pop();
        //5.取得栈中的元素个数
        stack.size();
        //6.判断栈是否为空
        stack.isEmpty();
    }

1.3栈的模拟实现

        由于栈是单向进行操作,所以我们可以用数组来模拟实现栈。

public class MyStack {
     //用数组模拟栈
     public int []elem;
     //有效数
     public int usesize;
     //初始数组大小
     public static final int DEFAULT_SIZE=10;

     //初始化数组
     public MyStack(){
         elem=new int[DEFAULT_SIZE];
     }

     //模拟入栈
     public void push(int val){
         //如果栈为满就扩容
         if(isFull()){
             grow();
         }
         //反之,插入元素,并增加有效数
         elem[usesize]=val;
         usesize++;
     }

    //模拟出栈
     public int pop(){
        //如果栈为空 就放回-1
        if(isEmpty()){
            return -1;
        }
        //先定义一个返回值
        int val=elem[usesize];
        //将数组减一 达到出栈的效果
        usesize--;
        //返回出栈的数字
        return val;
     }

     //模拟返回栈顶元素
     public int peek(){
         //如果栈为空 就放回-1
         if(isEmpty()){
             return -1;
         }
         //放回数组第一个元素,模拟返回栈顶元素
         return elem[usesize];
     }
    
     //模拟返回栈中元素的个数
     public int size(){
         //这边的有效数即栈的个数
         return usesize;
     }

    //打印栈中元素个数
    public void printStack(){
        for(int i=0;i<usesize;i++){
            System.out.println(elem[i]+" ");
        }
    }
     
    //判断是否为满
     public boolean isFull(){
         //如果有效数==数组的长度 那么该数组就满了
         return usesize==elem.length;
     }

     //扩容
     public void grow(){
        //扩容2倍
         elem=Arrays.copyOf(elem,elem.length*2);
     }
    
     //判断是否为空
     public boolean isEmpty(){
         //如果有效数为0,那么就表示该数组中一个元素都没有,即栈为空
         return usesize==0;
     }

}

2.队列(Queue)

2.1概念

        队列一端进行增加数据,另一端进行删除数据,增加数据的一端为尾,而它的头就进行删除数据,依据先进先出原则。

        队头:进行数据的删除。

        队尾:进行数据的增加。

        先进先出:也可称为后进后出,就像现实中的排队打饭,从队尾开始排队,要想打到饭出去就只能到队头的时候,这就是先进先出/后进后出。

2.2队列的使用

        在Java中,队列(Queue)是一个接口,底层通过链表来实现,所以示例化时需要依附于LinkedList对象,因为LinkedList实现了队列的接口

1.Queue: 创建空的队列

2.void offer(E e):为一个栈添加元素

3.E poll():取得队头元素并删除

4.E peek():取得队头元素不删除

5.int size():取得队列中元素的个数

6.boolean isEmpty(): 判断队列是否为空,是返回treu 不是返回false

public static void main(String[] args) {
        //1.创建空队列
        Queue<Integer> queue=new LinkedList<>();
        //2.为队列增加元素
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        System.out.println(queue);
        //3.取得队头元素并删除
        queue.poll();
        //4.取得队头元素不删除
        queue.peek();
        //5.取得队列中元素的个数
        queue.size();
        //6.判断队列是否为空
        queue.isEmpty();
    }

2.3队列模拟实现

        由于栈是进行双向操作的,所以这边我们使用链表来模拟实现栈。

public class MyQueue {
    //因为使用链表模拟
    //所以先创建Node节点
    static class Node {
        private int val;
        private Node next;
        private Node prev;

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

    //链表头
    public Node front;
    //链表尾
    public Node rear;

    //模拟实现增加元素
    public void offer(int val) {
        //创建node变量接收要增加的元素
        Node node = new Node(val);
        //如果列表初始状态为空,
        //那么加入的第一个元素就是这个链表的头尾
        if (front == null) {
            front = node;
            rear = node;
        }
        //反之
        //因为队列增加元素是在队尾
        //所以这边我们使用尾插法模拟增加元素
        rear.next = node;//将队列的的最后一个元素的下一个指向指向node
        node.prev = rear;//将node的上一个指向指向列表的最后一个元素
        rear = node;//将队列的尾部标识移动到新增加的元素的位置
    }

    //模拟实现取得队头元素
    public int peek() {
        //如果队列为空,返回-1
        if (front == null) {
            return -1;
        }


        //反之 返回头元素的值
        return front.val;
    }

    //模拟实现取得队头元素并删除
    public int poll() {
        //如果队列为空,返回-1
        if (front == null) {
            return -1;
        }
        //先取得队头的元素
        int val = front.val;
        //将队头的元素移除
        front = front.next;//队头为队头的下一元素
        front.prev = null;//将对头的上一个指向改为null
        return val;
    }

    //模拟实现取得队列中的元素个数
    public int size() {
        //定义一个cur元素为队头
        Node cur = front;
        //计数
        int count = 0;
        //但cur不为空时,计数一次并间cur往后移动一位
        while (cur == null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

    //模拟实现判断队列是否为空
    public boolean isEmpty() {
        //如果队头没有元素 那么这个队列就为空
        return front == null;
    }

    //打印队列的元素
    public void printfQueue() {
        Node cur = front;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
    }

}

       


http://www.kler.cn/a/599748.html

相关文章:

  • CSS 中text - shadow和box - shadow原理、属性的使用方法及区别
  • 鸿蒙进行视频上传,使用 request.uploadFile方法
  • Android 13系统定制实战:基于系统属性的音量键动态屏蔽方案解析
  • [AI速读]用持续集成(CI)优化芯片验证环境:Jenkins与EDA工具的实战指南
  • 【Linux学习笔记】gcc编辑器和动静态库的深度剖析
  • SAP-ABAP:SAP事务码SE14深度解析:数据库表管理核心工具
  • mysql传统主从模式下,主从中断接续
  • 探究Three.js中模型移动与旋转的交互逻辑
  • venv 和 conda 哪个更适合管理python虚拟环境
  • 内网穿透的应用-本地部署ChatTTS教程:Windows搭建AI语音合成服务的全流程配置
  • LeetCode讲解篇之456. 132 模式
  • 鸿蒙生态开发
  • OSI 模型详解及详细知识总结
  • C# CancellationTokenSource CancellationToken Task.Run传入token 取消令牌
  • 使用 Nginx 实现镜像流量:提升系统可用性与负载均衡
  • 深入剖析ReLU激活函数:特性、优势与梯度消失问题的解决之道,以及Leaky ReLU 和 Parametric ReLU
  • WordPress分类目录绑定二级域名插件
  • 【Vitis AI】FPGA设备使用PyTorch 运行 ResNet18获得10000fps
  • 制作PaddleOCR/PaddleHub的Docker镜像
  • L2-052 吉利矩阵