Java数据结构-队列

news2024/11/28 9:31:55

目录

  • 1. 队列概念
  • 2. 模拟实现队列
    • 2.1 链式队列
    • 2.2 循环队列
  • 3. 双端队列
  • 4. 队列的应用
    • 4.1 用队列实现栈
    • 4.2 用栈实现队列

1. 队列概念

队列是一种只能在一端进行插入数据操作,另一端进行删除数据操作的数据结构,插入数据的叫队尾,删除数据的叫队头。类似于生活中的排队打饭,进入队列中只能从队伍的后面进入,出队只能在队头出。队列是一种先进先出的数据结构。

2. 模拟实现队列

队列有链式结构和顺序结构两种,Java中的Queue接口底层是链式结构,包含方法如下:
在这里插入图片描述
add和offer表示入队,remove和poll表示出队,element和peek表示获取队头的元素(不删除)。

2.1 链式队列

Java的Queue底层是用双向链表实现的,所以我们也用双向链表模拟实现

public class MyQueue<E> {

    //使用双向链表
    static class ListNode {
        public ListNode next;//前驱
        public ListNode prev;//后继
        public Object val;//值

        //构造方法用于初始化
        public ListNode(Object val) {
            this.val = val;
        }
    }

    public ListNode head;//头
    public ListNode tail;//尾

    //入队->只能从尾部入队(尾插)
    public void offer(E val) {
        ListNode newNode = new ListNode(val);
        //第一次入队
        if (tail == null) {
            head = tail = newNode;
            return;
        }
        tail.next = newNode;
        newNode.prev = tail;
        tail = newNode;
    }

    //出队->只能从头部出队(头删)
    public E poll() {
        if (empty()) {
            return null;
        }
        Object ret = head.val;

        head = head.next;
        head.prev = null;
        return (E) ret;
    }

    //获取队头元素
    public E peek() {
        if (empty()) {
            return null;
        }
        return (E)head.val;
    }

    //判断队列是否为空
    public boolean empty() {
        return head == null;
    }

}

2.2 循环队列

循环队列是使用数组实现的,循环队列的结果如图
在这里插入图片描述
循环队列的原理: 循环队列看似乎结果成环,其实底层是连续的数组,实现循环的是队头(front)和队尾(rear)两个变量,front下标表示队列的第一个元素,rear下标则是队尾的下一个位置。队列为空的条件:front==rear,队列满了的条件:(rear+1)%数组长度 ==front
在这里插入图片描述

代码实现:

public class round_robinQueue<E> {
    public Object[] elem;//数组
    public int front;//队头
    public int rear;//队尾

	//k表示容量
    public round_robinQueue(int k) {
        this.elem = new Object[k + 1];//浪费一个空间,所以申请了k+1个空间
    }

    //入队一个元素
    public boolean offer(E value) {
        //满了不能插
        if (isFull()) {
            return false;
        }
        elem[rear] = value;
        rear = (rear + 1) % elem.length;
        return true;
    }

    //出队一个元素
    public boolean poll() {
        if (isEmpty()) {
            return false;
        }
        front = (front + 1) % elem.length;
        return true;
    }

    //获取队头元素
    public E getFront() {
        if (isEmpty()) {
            return null;
        }
        return (E) elem[front];
    }

    //获取队尾元素
    public E Rear() {
        if (isEmpty()) {
            return null;
        }
        //rear指向的是下一个位置,不是最后一个元素,如果rear=0,会越界
        if (rear == 0) {
            return (E) elem[elem.length - 1];
        }
        return (E) elem[rear - 1];
    }

    public boolean isEmpty() {
        return front == rear;
    }

    public boolean isFull() {
        return (rear + 1) % elem.length == front;
    }
}

3. 双端队列

双端队列指允许两端都可以进行入队、出队操作的队列,Java中可以使用Deque这个接口,有顺序实现ArrayDeque和链式实现LinkedList

4. 队列的应用

4.1 用队列实现栈

在这里插入图片描述

题目链接:用队列实现栈
解题思路: 首先,只使用一个队列是不行的,需要两队列。
实现逻辑: 入栈操作:将元素放入不为空的队列(如果是第一次入栈,两个队列都可以)。出栈操作:将不为空的队列中的n-1个元素放入另一个队列中,最后将剩下的元素出队。获取栈顶元素:将不为空的队列中所有的元素放入另一个队列中,返回最后一个元素即可
代码:

class MyStack {

    public Queue<Integer> q1;
    public Queue<Integer> q2;

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

    //入栈
    public void push(int x) {
        //如果都为空,在q1中添加
        if (empty()) {
            q1.offer(x);
            return;
        }
        if (q1.isEmpty()) {
            q2.offer(x);
        } else {
            q1.offer(x);
        }
    }

    //出栈
    public int pop() {
        //如果模拟栈为空,返回
        if (empty()) {
            return -1;
        }
        if (!q1.isEmpty()) {
            //q1不为空
            int size = q1.size();
            for (int i = 0; i < size - 1; i++) {
                q2.offer(q1.poll());
            }
            return q1.poll();
        } else {
            int size = q2.size();
            for (int i = 0; i < size - 1; i++) {
                q1.offer(q2.poll());
            }
            return q2.poll();
        }
    }

    //获取栈顶元素
public int top() {
        //如果模拟栈为空,返回
        if (empty()) {
            return -1;
        }
        if (!q1.isEmpty()) {
            //q1不为空
            int size = q1.size();
            int ret = -1;
            for (int i = 0; i < size; i++) {
                ret = q1.poll();
                q2.offer(ret);
            }
            return ret;
        } else {
            int size = q2.size();
            int ret = -1;
            for (int i = 0; i < size; i++) {
                ret = q2.poll();
                q1.offer(ret);
            }
            return ret;
        }
    }

    //判断模拟栈是否为空,如果两个队列都为空则为空
    public boolean empty() {
        return q1.isEmpty() && q2.isEmpty();
    }
}

4.2 用栈实现队列

在这里插入图片描述
题目链接: 用栈实现队列
解题思路: 使用两个栈实现队列,入队和出队的逻辑:其中一个栈(s1)只进行入栈操作,表示入队列;另一个栈(s2)只进行出栈操作,表示出队,如果s2空了再将s1中所有元素都入s2这个栈

代码:

class MyQueue {

    public Stack<Integer> s1;
    public Stack<Integer> s2;

    public MyQueue() {
        s1 = new Stack<>();
        s2 = new Stack<>();
    }

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

    public int pop() {
        if (empty()) {
            return -1;
        }
        //如果s2为空,把s1的所有元素拿过来
        if (s2.empty()) {
            while (!s1.empty()) {
                s2.push(s1.pop());
            }
        }
        return s2.pop();
    }

    public int peek() {
        if (empty()) {
            return -1;
        }
        //如果s2为空,把s1的所有元素拿过来
        if (s2.empty()) {
            while (!s1.empty()) {
                s2.push(s1.pop());
            }
        }
        return s2.peek();
    }

    public boolean empty() {
        return s1.empty() && s2.empty();
    }
}

今天的内容就到这里,感谢老铁们的点赞、收藏、评论~❤

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1577818.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于巴法云物联网云平台构建可视化控制网页(以控制LED为例)

0 前言 如今大大小小的物联网云平台非常多&#xff0c;但大部分要收取费用&#xff0c;免费的物联网云平台功能则有很多限制使用起来非常不方便。以百度云物联网云平台为例&#xff0c;它的物可视不支持发布主题&#xff0c;等于可视化界面只能作为数据监控而不具备双向通信的…

小红书广告推广如何开户及费用攻略?

随着小红书平台影响力的日益增强&#xff0c;越来越多的品牌和商家选择在此进行广告推广&#xff0c;以触达其庞大的年轻且具有高度消费力的用户群体。面对复杂的开户流程、多样化的计费模式以及激烈的竞争环境&#xff0c;许多广告主难免感到困扰。云衔科技的专业服务应运而生…

RISC-V特权架构 - 模式切换与委托

RISC-V特权架构 - 模式切换与委托 1 导致模式切换的常见动作2 异常处理规则3 异常处理时模式切换3.1 在U模式下&#xff0c;发生异常3.2 在S模式下&#xff0c;发生异常3.3 在M模式下&#xff0c;发生异常 4 系统调用时模式切换5 中断处理时模式切换 本文属于《 RISC-V指令集基…

通过网络api获取日期对应的节假日信息

网络接口获取链接&#xff1a;免费节假日API_原百度节假日API HolidayJudge.h #pragma once#include <QtWidgets/QWidget> #include "ui_HolidayJudge.h"enum DATESTATE {WORK0,//工作日DAYOFF,//休息日HOLIDAY//节假日 };class HolidayJudge : public QWidg…

隐藏在计算过程中的数据超限

【题目描述】 输入两个正整数&#xff0c;输出&#xff0c;保留5位小数。输入包含多组数据&#xff0c;结束标记为n&#xff1d;m&#xff1d;0。提示&#xff1a;本题有陷阱。 【样例输入】 2 4 65536 655360 0 0 【样例输出】 Case 1: 0.42361 Case 2: 0.00001 【题…

AI日报:北大Open Sora视频生成更强了;文心一言可以定制你自己的声音;天工 SkyMusic即将免费开放;

&#x1f916;&#x1f4f1;&#x1f4bc;AI应用 北大Open Sora视频生成更强了!时长可达10秒&#xff0c;分辨率更高 【AiBase提要:】 ⭐️ Open-Sora-Plan v1.0.0模型发布 显著提升视频生成质量和文本控制能力 ⭐️ 支持华为昇腾910b芯片&#xff0c;提升运行效率和质量。 ⭐…

如何实现OpenHarmony的OTA升级?

OTA简介 随着设备系统日新月异&#xff0c;用户如何及时获取系统的更新&#xff0c;体验新版本带来的新的体验&#xff0c;以及提升系统的稳定性和安全性成为了每个厂商都面临的严峻问题。OTA&#xff08;Over the Air&#xff09;提供对设备远程升级的能力。升级子系统对用户…

麻了,一面就这么难

总体而言&#xff0c;整个过程更看你回答的条理与深度&#xff0c;不太需要面面俱到&#xff0c;有自己的理解和思考反而会加分&#xff0c;不需要每道题都回答得百分百&#xff0c;有些问题属于面试官顺带提一嘴&#xff0c;但重点问题要答好。 一面 介绍下项目&#xff0c;因…

《最佳实践之》GPS NMEA-0183 协议, 解析 $GPRMC 协议

一&#xff0c;了解 GPS NMEA-0183 协议 需要基础物联网对接知识&#xff0c;需要对解析协议有一定认识。 如果不知道怎么连接硬件&#xff0c;请看我的另一篇博客&#xff1a;https://blog.csdn.net/Crazy_Cw/article/details/126613967 这篇文章只说明&#xff0c;如何解析协…

AI编程案例002/ 根据草图设计小红书封面

之前看OpenAI发布会&#xff0c;给个草图能设计个网站。 今天试了一下&#xff0c;给ChatGpt一个封面的设计草图&#xff0c;让ChatGpt编程实现一个拼图封面。 需求如下&#xff1a; 上传四张图片图片按草图排列成不同的布局&#xff0c;每一种布局是一个封面。下面草图的布…

Godot 常用UI+布局容器简单介绍

文章目录 前言相关链接Canvasitem&#xff1a;画布Control&#xff1a;UI布局基类Container&#xff1a;布局容器基类AspectRatioContainer&#xff1a;伸缩居中布局BoxContainer&#xff1a;盒子布局ColorPicker:取色器 CenterContainer&#xff1a;不伸缩居中FlowContainer&a…

软件设计师:下午题(试题三)历年真题

2021年下半年 2021年上半年 2020年下半年 2019年下半年 2019年上半年 2018年下半年 2018年上半年 2017年下半年 后续知识引入 2017年上半年 2016年下半年 2016年上半年 2015年下半年 2015年上半年 2014年下半年 2014年上半年 2013年下半年 2013年上半年 2012年下半年 2012年…

Flink运行机制相关概念介绍

Flink运行机制相关概念介绍 1. 流式计算和批处理2. 流式计算的状态与容错3. Flink简介及其在业务系统中的位置4. Flink模型5. Flink的架构6. Flink的重要概念7. Flink的状态、状态分区、状态缩放&#xff08;rescale&#xff09;和Key Group8. Flink数据交换9. 时间语义10. 水位…

给他个卖票的机会,他能卖出负数票. 多线程安全问题演示

文章目录 1.1 线程安全产生的原因注意 : 以上代码是有问题 , 接下来继续改进通过上述代码的执行结果 , 发现了出现了负号票 , 和相同的票 . 说明数据出现安全问题 1.2 线程的同步1.3 同步代码块1.4 同步方法1.5 Lock锁 1.1 线程安全产生的原因 多个线程在对共享数据进行读改写…

关系(三)利用python绘制相关矩阵图

关系&#xff08;三&#xff09;利用python绘制相关矩阵图 相关矩阵图&#xff08;Correlogram&#xff09;简介 相关矩阵图既可以分析每对变量之间的相关性&#xff0c;也可以分析单变量的分布情况。相关性以散点图的形式可视化&#xff0c;对角线用直方图/密度图表示每个变量…

MySQL 底层数据结构 聚簇索引以及二级索引 Explain的使用

数据结构 我们知道MySQL的存储引擎Innodb默认底层是使用B树的变种来存储数据的 下面我们来复习一下B树存储 B树存储 哈希存储的区别 哈希存储,只能使用等值查询 B树与B树存储 我们知道B树实际上就是B树的变种 那么为啥使用B树而不是使用B树呢? 我们知道效率的高低主要取决于…

【JavaScript】作用域和闭包

作用域 作用域是程序源代码中定义的范围。JavaScript采用词法作用域&#xff0c;也就是静态作用域。所谓词法作用域就是在函数定义的时候就已经确定了。 let value 1 function foo(){console.log(value) } function bar(){let value 2foo() } bar() // 1变量对象是当前代码…

2.基础乐理-唱名的来历,简谱的构造

前置内容&#xff1a;1.唱名与记住唱名的方法 唱名的来历&#xff1a; 很久很久以前&#xff08;公元前&#xff09;各个文明开始诞生和慢慢发展&#xff0c;随着文明的发展&#xff0c;各个文明都开始出现自己的音乐&#xff0c;根据考古学家的发现在 公元前1800年&#xff…

【随笔】Git 高级篇 -- 整理提交记录(下)rebase(十六)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

每日汇评:地缘冲突休战会阻碍黄金创纪录的涨势吗?

尽管以色列与哈马斯的地缘政治紧张局势有所缓和&#xff0c;金价仍冲破 2350 美元&#xff0c;创下新高&#xff1b; 对央行黄金购买量激增的预期抵消了美国非农就业数据主导的美联储强硬押注&#xff1b; 在美国CPI数据公布之前&#xff0c;由于 RSI 极度超买&#xff0c;金价…