【数据结构】循环队列(数组实现)

目录

一、循环队列定义

怎么使一个数组在逻辑上呈“环状”呢?

 二、循环队列与顺序队列的差异

1、存储方式:

2、操作方式:

3、空间利用率:

4、循环队列判断队空的方式:

5、循环队列判断队满的方式

完整测试代码及注释: 

总结:


一、循环队列定义

将顺序存储队列的元素的一维数组首尾相接,形成一个环状,如下图所示,这种形式表示的队列称为循环队列。循环队列仍然是顺序队列结构,只是逻辑上和前面的顺序队列有所不同。

#define MAXLEN 6           // 定义环形队列的最大长度为 6typedef int DataType;     // 定义数据类型为整型typedef struct CircularQueue  // 定义环形队列的结构体
{DataType a[MAXLEN];   // 定义存储数据的数组int front, rear;      // 定义队头和队尾指针int size;             // 定义队列元素个数
} CQueue;void InitCQueue(CQueue* q)  // 初始化环形队列
{q->front = q->rear = 0; // 队头和队尾指针都指向队列的开始位置q->size = 0;            // 队列元素个数为 0,即初始为空队列
}

怎么使一个数组在逻辑上呈“环状”呢?

在数据结构中,可以使用一个 front 指针和一个 rear 指针来表示环状队列的队头和队尾位置,当 rear 指针移动到数组的最后一个位置时,如果再有元素需要入队,那么应该将 rear 指针指向数组的第一个位置。同样地,当 front 指针移动到数组的最后一个位置时,如果还有元素需要出队,那么应该将 front 指针指向数组的第一个位置。

具体实现方法如下:

  1. 初始化:定义一个数组和两个指针 front 和 rear,初始化时,将 front 指针和 rear 指针都指向数组的第一个位置。

  2. 入队:如果队列未满,则将元素插入 rear 指向的位置,然后将 rear 指针后移一位。当 rear 指针移动到数组的最后一个位置时,若队列未满,则将 rear 指针指向数组的第一个位置。

  3. 出队:如果队列非空,则将队头元素取出,然后将 front 指针后移一位。当 front 指针移动到数组的最后一个位置时,只要队列非空,就将 front 指针指向数组的第一个位置。

假设队列开辟的数组单元数为MAXSIZE,它的数组下标在0~MAXSIZE-1之间,若使队头或队尾增1,且使front和rear指针对应的数组下标保持在数组范围内,可以利用取模运算实现。


例如,在下图所示的循环队列示意图最大空间为MAXSIZE=8,数组下标为0~7之间。

非空队时如图(2)中队头指针front指向队列中队头元素的前一个位置队尾指针rear 指向队列的队尾元素位置。

  •         入队时的队尾指针加1操作修改为: rear=(rear+1)%MAXSIZE;
  •         出队时的队头指针加1操作修改为:front=(front+1)%MAXSIZE;

入队代码实现: 

void CQueuePush(CQueue* q, DataType x)   // 元素入队
{assert(q);  // 判断 q 是否为空if (!CQueueFull(q))  // 如果队列未满{q->rear = (q->rear + 1) % MAXLEN;   // 队尾指针后移一位q->a[q->rear] = x;  // 在队尾处添加元素q->size++;  // 队列元素个数加 1}else    // 队列已满,无法添加数据{printf("队列已满,无法添加数据!\n");exit(-1);}
}

 出队代码实现: 

void CQueuePop(CQueue* q)   // 元素出队
{assert(q);  // 判断 q 是否为空if (!CQueueEmpty(q))    // 如果队列非空{q->front = (q->front + 1) % MAXLEN; // 队头指针后移一位q->size--;  // 队列元素个数减 1}else    // 队列已空,无法删除数据{printf("队列已空,无法删除数据!\n");exit(-1);}
}


 二、循环队列与顺序队列的差异

  • 1、存储方式:

    • 顺序队列:使用数组作为底层数据结构,按照顺序存储元素。
    • 循环队列:仍然使用数组作为底层数据结构,但是通过循环利用数组的空间,实现循环存储。
  • 2、操作方式:

    • 顺序队列:使用两个指针front和rear分别表示队头和队尾,元素入队时rear指针后移,元素出队时front指针后移。
    • 循环队列:同样使用两个指针front和rear表示队头和队尾,但是在数据满或空的状态下,指针继续向后移动的时候保持循环关系。
      • 入队时队尾指针+1:rear=(rear+1)%MAXSIZE;
      • 出队时队头指针+1:front=(front+1)%MAXSIZE;
  • 3、空间利用率:

    • 顺序队列:存储元素的空间是连续的,当队列未满但是数组的末尾已经被利用时,无法继续插入元素。
    • 循环队列:通过循环利用数组空间,解决了顺序队列存储空间的浪费问题,可以实现更高的空间利用率。

4、循环队列判断队空的方式:

图(1)中队头与队尾指针指向同一位置时为空队,判断方法与顺序队列一致。

 代码实现:

int CQueueEmpty(CQueue* q)  // 判断队列是否为空
{assert(q);  // 判断 q 是否为空if (q->front == q->rear)  // 通过队头和队尾指针是否相等,判断队列是否为空{return 1;   // 队列为空}return 0;       // 队列非空
}

5、循环队列判断队满的方式

由 图(3) 可见,循环队列解决了顺序队列中“假溢出”的现象,充分利用了固定长度的队列中的空间。我们知道,在长度不可增长的顺序队列中,判断队列是否队满的条件是rear==MAXLEN。那么在循环队列中,我们判断队满的方式则为:(rear+1)%MAXLEN==front;  


 

代码实现:

int CQueueFull(CQueue* q)   // 判断队列是否为满
{assert(q);  // 判断 q 是否为空if ((q->rear + 1) % MAXLEN == q->front)  // 通过队尾和队头指针是否相邻,判断队列是否为满{return 1;   // 队列为满}return 0;       // 队列未满
}

我们理解完顺序队列与循环队列的差异后,在固定长度代码的基础上对front、rear指针的移动判满操作进行修改即可得到循环队列的代码。


完整测试代码及注释: 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>#define MAXLEN 6           // 定义环形队列的最大长度为 6typedef int DataType;     // 定义数据类型为整型typedef struct CircularQueue  // 定义环形队列的结构体
{DataType a[MAXLEN];   // 定义存储数据的数组int front, rear;      // 定义队头和队尾指针int size;             // 定义队列元素个数
} CQueue;void InitCQueue(CQueue* q)  // 初始化环形队列
{q->front = q->rear = 0; // 队头和队尾指针都指向队列的开始位置q->size = 0;            // 队列元素个数为 0,即初始为空队列
}int CQueueFull(CQueue* q)   // 判断队列是否为满
{assert(q);  // 判断 q 是否为空if ((q->rear + 1) % MAXLEN == q->front)  // 通过队尾和队头指针是否相邻,判断队列是否为满{return 1;   // 队列为满}return 0;       // 队列未满
}int CQueueEmpty(CQueue* q)  // 判断队列是否为空
{assert(q);  // 判断 q 是否为空if (q->front == q->rear)  // 通过队头和队尾指针是否相等,判断队列是否为空{return 1;   // 队列为空}return 0;       // 队列非空
}void CQueuePush(CQueue* q, DataType x)   // 元素入队
{assert(q);  // 判断 q 是否为空if (!CQueueFull(q))  // 如果队列未满{q->rear = (q->rear + 1) % MAXLEN;   // 队尾指针后移一位q->a[q->rear] = x;  // 在队尾处添加元素q->size++;  // 队列元素个数加 1}else    // 队列已满,无法添加数据{printf("队列已满,无法添加数据!\n");exit(-1);}
}void CQueuePop(CQueue* q)   // 元素出队
{assert(q);  // 判断 q 是否为空if (!CQueueEmpty(q))    // 如果队列非空{q->front = (q->front + 1) % MAXLEN; // 队头指针后移一位q->size--;  // 队列元素个数减 1}else    // 队列已空,无法删除数据{printf("队列已空,无法删除数据!\n");exit(-1);}
}int CQueueTop(CQueue* q)   // 获取队首元素
{if (!CQueueEmpty(q))    // 如果队列非空{return q->a[q->front + 1];  // 返回队头下一个位置的元素}else    // 队列已空,无法获取队首数据{printf("队列已空,无法获取队首数据!\n");exit(-1);}
}int CQueueTail(CQueue* q)   // 获取队尾元素
{if (!CQueueEmpty(q))    // 如果队列非空{return q->a[q->rear];   // 返回队尾位置的元素}else    // 队列已空,无法获取队尾数据{printf("队列已空,无法获取队尾数据!\n");exit(-1);}
}int main()
{CQueue q;InitCQueue(&q);CQueuePush(&q, 1);CQueuePush(&q, 2);CQueuePush(&q, 3);CQueuePush(&q, 4);CQueuePush(&q, 5);CQueuePop(&q);CQueuePop(&q);CQueuePop(&q);CQueuePop(&q);//CQueuePop(&q);int x;x = CQueueTop(&q);printf("%d\n", x);x = CQueueTail(&q);printf("%d\n", x);return 0;
}

总结:

循环队列通过环形数组的设计,充分利用了存储空间,并实现了高效的元素入队和出队操作。在使用循环队列时,需要特别注意队列为空和队列满的判断,避免出现错误。

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

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

相关文章

axure RP9.0安装字体图标库fontawesome

字体图库地址: Font AwesomeThe internets icon library toolkit. Used by millions of designers, devs, & content creators. Open-source. Always free. Always awesome.https://fontawesome.com/v6/download进入后下载想要的版本如我是6.3 下载后得到压缩包,解压之后…

机器学习笔记 - 从2D数据合成3D数据

一、3D 数据简介 人们一致认为,从单一角度合成 3D 数据是人类视觉的一项基本功能,这对计算机视觉算法来说极具挑战性。但随着 LiDAR、RGB-D 相机(RealSense、Kinect)和 3D 扫描仪等 3D 传感器的可用性和价格的提高,3D 采集技术的最新进展取得了巨大飞跃。 与广泛使用的 2D…

Mybatis-Plus乐观锁配置使用流程【OptimisticLockerInnerInterceptor】

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家:人工智能学习网站 1.乐观锁实现 1.配置插件 1.XML方式 <bean class"com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerI…

C# .Net 开发设计多用户网上商城源码_OctShop

随着C#在TIOBE编程语言排行不断上升&#xff0c;这也标志着越来越多的程序员开始使用C#来开发项目了。在TIOBE2023年10月公布的排行中&#xff0c;C#和Java之间的差距越来越小了&#xff0c;仅为1.2%&#xff0c;随着C# .NetCore的免费开源&#xff0c;这一上升的趋势越来越明显…

MySQL视图特性

目录 视图概念基本使用创建视图修改视图会影响基表修改基表会影响视图删除视图 视图规则和限制 视图概念 视图是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表&#xff0c;基表的数据变…

Python 编写代码的工具-交互式环境

交互式环境意思就是我们输入一行代码&#xff0c;按回车&#xff0c;代码就会立马执行并产生结果和显示在窗口中。 要打开Python交互式环境&#xff0c;具体操作如下&#xff08;win系统&#xff09;&#xff1a; 键盘WINR&#xff0c;再输入指令“cmd”,就可以打开命令提示符…

win下持续观察nvidia-smi

简介&#xff1a;在Windows操作系统中&#xff0c;没有与Linux中watch命令直接对应的内置工具&#xff0c;但有1种方法快速简单的方法可以实现类似的效果&#xff0c;尤其是用于监控类似于nvidia-smi的命令输出。 历史攻略&#xff1a; Python&#xff1a;查看windows下GPU的…

数据库攻防学习之MySQL

MySQL 0x01mysql学习 MySQL 是瑞典的MySQL AB公司开发的一个可用于各种流行操作系统平台的关系数据库系统&#xff0c;它具有客户机/服务器体系结构的分布式数据库管理系统。可以免费使用使用&#xff0c;用的人数很多。 0x02环境搭建 这里演示用&#xff0c;phpstudy搭建的…

华为端口隔离高级用法经典案例

最终效果&#xff1a; pc4不能ping通pc5&#xff0c;pc5能ping通pc4 pc1不能和pc2、pc3通&#xff0c;但pc2和pc3能互通 vlan batch 2 interface Vlanif1 ip address 10.0.0.254 255.255.255.0 interface Vlanif2 ip address 192.168.2.1 255.255.255.0 interface MEth0/0/1 i…

基于SSM的校园快递管理系统

目录 前言 开发环境以及工具 项目功能介绍 学生&#xff1a; 管理员&#xff1a; 详细设计 获取源码 前言 本项目是一个基于IDEA和Java语言开发的基于SSM的校园快递管理系统应用。应用包含学生端和管理员端等多个功能模块。 欢迎使用我们的校园快递管理系统&#xff01;我…

厦门大学OpenHarmony技术俱乐部开创“1+N”新模式,加速推动产学研融合

12月29日,OpenHarmony技术俱乐部再添重将——在多方见证下,厦门大学OpenHarmony技术俱乐部在翔安校区益海嘉里楼报告厅正式揭牌成立,现场出席领导及师生代表近千人。 成立仪式现场 OpenHarmony技术俱乐部 携手厦门大学共绘开源生态新图景 OpenHarmony是由开放原子开源基金…

揭示AUTOSAR中隐藏的漏洞

AUTOSAR是一个普遍采用的软件框架&#xff0c;用于各种汽车零部件&#xff0c;如ABS, ECU,自动照明、环境控制、充电控制器、信息娱乐系统等。AUTOSAR的创建目的是促进汽车零部件之间形成标准接口&#xff0c;可以在不同制造商之间互通。 因此&#xff0c;任何配备微控制器(MC…

CGAL的无限制的Delaunay图

本章描述了构建L∞距离下线段Delaunay图的算法和几何特征。这些特征还包括绘制L∞距离下线段Delaunay图对偶&#xff08;即L∞距离下线段Voronoi图&#xff09;边缘的方法。L∞算法和特征依赖于欧几里得&#xff08;或L2&#xff09;距离下的线段Delaunay图算法和特征。L∞度量…

月报总结|Moonbeam 12月份大事一览

一转眼已经到年底啦。本月&#xff0c;Moonbeam基金会发布四个最新战略重点&#xff1a;跨链解决方案、游戏、真实世界资产&#xff08;RWA&#xff09;、新兴市场。其中在新兴市场方面&#xff0c;紧锣密鼓地推出与巴西公司Grupo RO的战略合作。 用户教育方面&#xff0c;为了…

大创项目推荐 深度学习人脸表情识别算法 - opencv python 机器视觉

文章目录 0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术 2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习人脸表情识别系…

优雅地展示20w单细胞热图|非Doheatmap 超大数据集 细胞数太多

单细胞超大数据集的热图怎么画&#xff1f;昨天刚做完展示20万单细胞的热图要这么画吗&#xff1f; 今天就有人发消息问我为啥他画出来的热图有问题。 问题起源 昨天分享完 20万单细胞的热图要这么画吗&#xff1f;&#xff0c;就有人问为啥他的数据会出错。我们先来看下他的…

imgaug库指南(一):从入门到精通的【图像增强】之旅

文章目录 引言imgaug简介安装和导入imgaug代码示例imgaug的强大之处和用途小结结尾 引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和…

(JAVA)-反射

什么是反射&#xff1f; 反射允许对成员变量&#xff0c;成员方法和构造方法的信息进行编程访问。 说简单点就是反射能将类里面的构造方法&#xff0c;成员变量,修饰符,返回值&#xff0c;注解&#xff0c;类型&#xff0c;甚至异常等类里面的所有东西都能够获取出来。 关于C…

团子杂记:SAP PS or 项目管理软件(PMIS )? PPM/P6

众所周知SAP的PS模块在项目型企业的SAP应用中扮演着核心角色&#xff0c;整个项目端到端的业务执行、财务核算、控制及分析都是通过PS作为主线&#xff0c;依赖于PS中的项目对象&#xff08;如WBS元素、网络活动等&#xff09;实现的。 在实施SAP的过程中&#xff0c;可以看到…

Nest 框架:解锁企业级 Web 应用开发的秘密武器(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…