循环队列

news2024/11/23 22:05:05

循环队列是一种线性数据结构,其操作表现基于 FIFO(First In First Out,先进先出)原则并且队尾被连接在队首以形成一个循环。

这种结构克服了普通队列在元素入队和出队时需要移动大量元素的缺点。

在循环队列中,当元素到达队列尾部时,下一个元素会循环回到队列的开头。

基本概念

  • 队列:队列是一种特殊的线性表,只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。队列中没有元素时,称为空队列。
  • 循环队列:为了充分利用向量空间,克服“假溢出”的现象,将队列存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空间,供队列循环使用。

循环队列的实现

循环队列通常使用数组来实现,并设置两个指针:front(队首指针)和rear(队尾指针)。它们分别指向队列的第一个元素和最后一个元素的下一个位置。

  • 初始化:设置front = 0rear = -1(或rear = 0,但此时队列为空,所以最好使用-1表示没有元素)。
  • 入队(enqueue)
    • 如果队列已满((rear + 1) % size == front),则无法添加新元素。
    • 否则,将元素添加到rear所指向的位置,并将rear向后移动一位((rear + 1) % size)。
  • 出队(dequeue)
    • 如果队列为空(front == rear),则无法删除元素。
    • 否则,从front所指向的位置删除元素,并将front向后移动一位((front + 1) % size)。
  • 判断队列是否为空front == rear
  • 判断队列是否已满(rear + 1) % size == front(注意这里使用取模运算来处理循环)

示例

假设有一个循环队列的容量为5,初始时front = 0rear = -1。当依次入队元素1, 2, 3, 4, 5后,front = 0rear = 4。如果再入队一个元素6,则rear会变为0(因为(4 + 1) % 5 = 0),此时frontrear再次相等,但队列并没有满,因为它们是循环的。

优点

  • 循环队列克服了假溢出的现象,能够更充分地利用存储空间。
  • 通过取模运算,可以快速定位队首和队尾的位置,实现高效的入队和出队操作。

注意事项

  • 在计算队列长度时,需要使用(rear - front + capacity) % capacity(如果rear < front)或(rear - front + 1)(如果rear >= front)来确保得到正确的长度。
  • frontrear相等时,需要根据队列的初始化情况来判断队列是为空还是满。一种常见的做法是在入队时检查是否已满,在出队时检查是否为空。

让我们看看代码吧~~~

public class Queue {
    private int[] elements;//用于存储队列元素的数组。
    private int size;//当前队列中的元素数量
    private int front; // 指向队列前端(即下一个出队元素)的索引
    private int rear;  // 指向队列后端(即下一个入队位置)的索引
    //构造函数:初始化一个大小为8的数组
    public Queue() {
        elements = new int[8];
        size = 0;//表示队列当前为空
        front = 0;//表示队列的前端在数组的起始位置
        rear = -1;//表示队列的后端还没有放置任何元素(即将要放置的第一个元素会在索引0处)
    }
    public void enqueue(int v) {
        if (size == elements.length) {//检查队列是否已满(即 size 是否等于 elements 的长度)
            //如果队列已满,则创建一个新的、容量是原来两倍的数组
            int[] newElements = new int[elements.length * 2];
            for (int i = 0; i < size; i++) {
                newElements[i] = elements[(front + i) % elements.length];
            }
            elements = newElements;//将elements的引用更新为新创建的数组newElements
            front = 0;
            rear = size - 1;
        }
        rear = (rear + 1) % elements.length;
        elements[rear] = v;
        size++;
    }

    public int dequeue() {
        if (empty()) {//检查队列是否为空(使用empty()方法)。如果队列为空,则抛出一个运行时异常。
            throw new RuntimeException("Queue is empty");
        }
        int v = elements[front];//获取front所指向的元素的值,并将其存储在变量v中
        front = (front + 1) % elements.length;//front指针以指向下一个元素
        size--;
        return v;
    }
//如果size为0,则返回true;否则返回false
    public boolean empty() {
        return size == 0;
    }

    public int getSize() {
        return size;
    }
}

我们把其中关键代码进行详细分析一下:

elements = newElements;//将elements的引用更新为新创建的数组newElements
front = 0;
rear = size - 1;

elements = newElements; 这行代码是一个赋值操作,它将 newElements 数组的引用赋值给 elements 变量。这意味着从现在开始,elements 和 newElements 都指向同一个数组对象在内存中的位置。

这样做有几个重要的影响:

  1. 内存管理:原数组elements(以及它之前指向的内存空间)不再被Queue类的任何成员变量引用。如果没有其他引用指向这个数组,那么它将成为垃圾回收(Garbage Collection)的目标,内存空间会被释放。
  2. 后续操作:之后对elements的任何操作(如添加、删除或访问元素)都会在新数组上进行,而不是在原来的小数组上。
  3. 引用更新:由于frontrear指针是相对于elements数组来计算的,所以在更新elements引用后,你需要相应地更新front的值(在你的例子中,它被设置为0),以确保后续操作正确。rear的值在复制元素后已经是正确的(即size - 1),因为它指向的是新数组中最后一个元素的下一个位置。
rear = (rear + 1) % elements.length;
elements[rear] = v;
size++;

这三行代码是队列实现中用于执行入队(enqueue)操作的关键部分,具体来说:

rear = (rear + 1) % elements.length;

这行代码是在更新队列的尾部(rear)指针。队列是一种先进先出(FIFO)的数据结构,新元素总是添加到队列的尾部。由于队列可能是一个循环队列,因此需要使用模运算(%)来确保rear的值在数组的有效索引范围内。如果rear加1后超出了数组的长度,模运算会将其“回绕”到数组的起始位置。

elements[rear] = v;

这行代码是将新元素v存储在数组的rear位置。这是队列中元素添加的实际操作,它将新元素放置在队列的尾部。

size++;

这行代码是增加队列的大小(size。队列的大小表示队列中当前存储的元素数量。每当一个新元素被添加到队列时,队列的大小就应该增加1。

综上所述,这三行代码共同完成了队列的入队操作:更新尾部指针、在尾部添加新元素、并增加队列的大小。

 

public int dequeue() {
        if (empty()) {//检查队列是否为空(使用empty()方法)。如果队列为空,则抛出一个运行时异常。
            throw new RuntimeException("Queue is empty");
        }
        int v = elements[front];//获取front所指向的元素的值,并将其存储在变量v中
        front = (front + 1) % elements.length;//front指针以指向下一个元素
        size--;
        return v;
    }

 int v = elements[front];

这里,elements 是一个数组(通常用于存储队列中的元素),而 front 是一个变量(通常是一个索引),指向队列中的第一个元素。这行代码从 elements 数组中取出 front 索引处的元素值,并将其存储在变量 v 中。

front = (front + 1) % elements.length;

这行代码更新 front 指针以指向队列中的下一个元素。由于队列可能是循环的(即数组首尾相连),所以使用模运算 % 来确保 front 的值在数组的有效范围内。如果 front 已经指向数组的最后一个元素,则将其重置为数组的起始位置(索引为 0)。

size--

 这行代码减少队列的 size 变量值,以反映队列中元素数量的减少。size 通常是一个变量,用于跟踪队列中当前元素的数量。

今天就先介绍这个了,我们下期见!

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

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

相关文章

轻松上手MYSQL:探索MySQL索引数据结构的奥秘-让数据库飞起来

​&#x1f308; 个人主页&#xff1a;danci_&#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL》&#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索MYSQL索引数据结构之旅✨ &#x1f44b; 大家好&#xff01;文本学习研…

Hadoop的读写流程

Hadoop分布式文件系统(HDFS)是Apache Hadoop项目的核心组件,它为大数据存储提供了一个可靠、可扩展的存储解决方案。本文将详细介绍HDFS的读写数据流程,包括数据的存储原理、读写过程以及优化策略。 一、HDFS简介 HDFS是一个高度容错的分布式文件系统,它设计用于运行在通…

python包管理器--- pip、conda、mamba的比较

1 pip 1.1 简介 pip是一个 Python 的包&#xff08;Package&#xff09;管理工具&#xff0c;用于从 PyPI 安装和管理 Python 标准库之外的其他包&#xff08;第三方包&#xff09;。从 Python 3.4 起&#xff0c;pip 已经成为 Python 安装程序的一部分&#xff0c;也是官方标准…

【chatbot-api开源项目】开发文档

chatbot-api 1. 需求分析1-1. 需求分析1-2. 系统流程图 2. 技术选型3. 项目开发3-1. 项目初始化3-2. 爬取接口获取问题接口回答问题接口创建对应对象 3-3. 调用AI3-4. 定时自动化回答 4. Docker部署5. 扩展5-1. 如果cookie失效了怎么处理5-2. 如何更好的对接多个回答系统 Gitee…

各种机器学习算法的应用场景分别是什么(比如朴素贝叶斯、决策树、K 近邻、SVM、逻辑回归最大熵模型)?

2023简直被人工智能相关话题席卷的一年。关于机器学习算法的热度&#xff0c;也再次飙升&#xff0c;网络上一些分享已经比较老了。那么今天借着查询和学习的机会&#xff0c;我也来浅浅分享下目前各种机器学习算法及其应用场景。 为了方便非专业的朋友阅读&#xff0c;我会从算…

揭秘神秘的种子:Adobe联合宾夕法尼亚大学发布文本到图像扩散模型大规模种子分析

文章链接&#xff1a;https://arxiv.org/pdf/2405.14828 最近对文本到图像&#xff08;T2I&#xff09;扩散模型的进展促进了创造性和逼真的图像合成。通过变化随机种子&#xff0c;可以为固定的文本提示生成各种图像。在技术上&#xff0c;种子控制着初始噪声&#xff0c;并…

FineReport简单介绍(2)

一、报表类型 模板设计是 FineReport 学习过程中的主要难题所在&#xff0c;FineReport 模板设计主要包括普通报表、聚合报表、决策报表三种设计类型。 报表类型简介- FineReport帮助文档 - 全面的报表使用教程和学习资料 二、聚合报表 2-1 介绍 聚合报表指一个报表中包含多个…

电商秒杀系统

一&#xff0c;细节 二&#xff0c;需要注意的细节 1.库存超卖问题 使用mysql数据库的 悲观锁 机制。在事务中使用 for update 语句&#xff0c;此时数据库会加锁&#xff0c;其他想要当前读的线程都会被阻塞&#xff0c;在事务处理完成之后释放这一条数据。该方法的缺点在于…

排序——希尔排序

希尔排序实际上是插入排序的优化&#xff0c;所以要先介绍插入排序。 目录 插入排序 思想 演示 代码实现 总结 希尔排序 思想 演示 代码 总结 插入排序 思想 又称直接插入排序。它的基本思想是将一个值插入到一个有序序列中。直至将所有的值都插入完。 演示 假设数…

工程设计问题---行星轮系设计问题

该问题的主要目标是使汽车传动比的最大误差最小。为了使最大误差最小&#xff0c;对自动行星传动系统的齿轮齿数进行了计算。该问题包含6个整数变量和11个不同几何约束和装配约束的约束。 参考文献&#xff1a; Abhishek Kumar, Guohua Wu, Mostafa Z. Ali, Rammohan Malliped…

国际统计年鉴(1995-2023年)

数据年份&#xff1a;1995-2023 数据格式&#xff1a;pdf、excel 数据内容&#xff1a;《国际统计年鉴》是一部综合性的国际经济社会统计资料年刊&#xff0c;收录了世界200多个国家和地区的统计数据&#xff0c;并对其中40多个主要国家和地区的经济社会发展指标及国际组织发布…

ARIMA模型与ARIMA-GARCH模型预测时间序列

上世纪 70 年代初&#xff0c;Ljung 等人提出 ARIMA 模型&#xff0c;又称求和自回归移动平均模型。其思想 是针对于非平稳时间序列进行数学建模&#xff0c;将其通过差分运算后 进行相关数据刻画 &#xff0c;变为一个平稳的新序列&#xff0c;进而进行相关数据的刻画。 自 1…

Element-UI - 解决el-table中图片悬浮被遮挡问题

在开发中&#xff0c;发现element-ui在el-table中添加图片悬浮显示时&#xff0c;会被单元格遮挡的问题。通过查询得到的解决办法&#xff0c;大多是修改.el-table类中相关样式属性&#xff0c;但经过验证发现会影响到其他正常功能的使用。对于此问题解决其实也并不难&#xff…

计算机网络知识点全面总结回顾

物理层 OSI模型&#xff1a;数据链路层&#xff08;流量控制&#xff09;&#xff0c;从传输层开始端到端&#xff1b;每一层的元素都称为实体&#xff0c;同一层的是对等实体&#xff1b;三个重要概念&#xff1a;服务&#xff08;下层为上层提供调用&#xff09;&#xff0c…

非连续分配管理方式(重点)

目录 一. 基本分页存储管理1.1 什么是分页存储1.2 页表 二. 基本地址变换机构三. 具有快表的地址变换机构3.1 什么是快表3.2 引入快表后, 地址的变换过程3.3 局部性原理 四. 两级页表4.1 单级页表存在什么问题?如何解决?4.2 两级页表的原理、逻辑地址结构4.3 如何实现地址变换…

机器学习笔记 - 用于3D点云数据分割的Point Net的训练

一、数据集简述 ​在本教程中,我们将学习如何在斯坦福 3D 室内场景数据集 ( S3DIS )上训练 Point Net 进行语义分割。S3DIS 是一个 3D 数据集,包含来自多栋建筑的室内空间点云,占地面积超过 6000 平方米。Point Net使用整个点云,能够执行分类和分割任务。如果你一直在关注 …

【机器学习】机器学习与教育科技在个性化教学中的融合应用与性能优化新探索

文章目录 引言机器学习与教育科技的基本概念机器学习概述监督学习无监督学习强化学习 教育科技概述学生学习行为分析个性化学习路径推荐智能化教育评估 机器学习与教育科技的融合应用实时学习数据分析数据预处理特征工程 学生成绩预测与优化模型训练模型评估 个性化学习路径推荐…

初始-Nativefier

--无奈只能靠自己 Nativefier 是什么&#xff1a; Nativefier 是一个命令行工具&#xff0c;仅仅通过一行代码就可以轻松地为任何的网站创建桌面应用程序&#xff0c;应用程序通过 Electron 打包成系统可执行文件&#xff08;如.app, .exe 等&#xff09;&#xff0c;可以运行在…

AI探索:最佳落地应用场景

如果说今年的风口&#xff0c;那一定是 AI。不过AI像一把双刃剑&#xff0c;既有助益也有风险。我们将从IBM Watson的高飞与坠落&#xff0c;到Google Allo的黯然失色&#xff0c;探索AI应用中的教训。同时&#xff0c;瑞幸咖啡的成功故事展现了凭借策略得当的AI应用&#xff0…

MySQL第三方图形化工具:DBeaver

操纵数据库的语言&#xff0c;基于功能划分为4类&#xff1a; 数据定义:DDL(Data Definition Language)库的创建删除、表的创建删除等 数据操纵:DML(Data ManipulationLanguage)新增数据、删除数据、修改数据等 数据控制:DCL(Data ControlLanguage)新增用户、删除用户、密码…