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

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;
        }
    }

}

       

相关文章:

  • 实现分布式锁需要考虑哪些问题?
  • 组播策略路由选择
  • SSH密钥认证 + 文件系统权限控制 + Git仓库配置+封存与解封GIT仓库
  • mac环境下chatwoot客服聊天docker本地部署+对接通义千问Qwen2.5
  • RAG 架构地基工程-Retrieval 模块的系统设计分享
  • 安卓15/aosp15/lineage21使用brunch编译老是报错OOM内存不足
  • 怎样才能把网页数据保存到网络上?
  • 【redis】在 Spring中操作 Redis
  • 设计模式之命令模式:原理、实现与应用
  • u-net系列算法
  • 工作相关记录
  • SpringSecurity——前后端分离登录认证
  • 区块链赋能项目包装融资:开启融资新范式
  • OpenCV中距离公式
  • Visual C++ 6.0(.dsp/.dsw)项目升级成VS2022
  • stm32g030移植RT-Thread
  • Enovia许可分析的自动化解决方案
  • STM32八股【1】-----启动流程和startup文件理解
  • dify中飞书插件安装及授权
  • AI Agent设计模式 四种高层次模式以及更具体的九种模式
  • 美国务卿与以色列总理通话,讨论加沙局势
  • 首次带人形机器人走科技节红毯,傅利叶顾捷:机器人行业没包袱,很多事都能从零开始
  • 流失79载,国宝文物“子弹库帛书”(二、三卷)回归祖国
  • 打击网络侵权盗版!四部门联合启动“剑网2025”专项行动
  • 梅花奖在上海|话剧《主角》:艺术与人生的交错
  • 经济日报评外卖平台被约谈:行业竞争不能背离服务本质