数据结构—循环队列(环形队列)
循环队列(环形队列)
- 循环队列的概念及结构
- 循环队列的实现
循环队列的概念及结构
循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

注:循环队列的空间大小是固定的
循环队列的实现
环形队列可以使用数组实现(超出数组的范围回到起始位置),也可以使用循环链表实现(尾指针的next指向头节点)。选用数组实现循环队列更好,因为数组缓存利用率更高,没有扩容的代价。
环形队列实际开辟的空间大小要比所存数据的队列长度多开辟一个空间的大小。如果环形队列实际开辟的空间大小和所存储数据个数一样时,会导致环形队列所处空的状态和满的状态是一样的。这样便无法区分。

因此环形队列必须多留出一个空间,这个空间不能存放数据,这样才能很好的区别环形队列的状态是空还是满。


在环形队列中,队列为空时,队头队尾指向同一个位置。当队列不为空时,队头指向插入的第一个数据,队尾指向最后一个数据的下一个位置。当tail+1等于front时,说明环形队列已满。
循环队列的定义
循环队列选择用数组实现,循环队列需要用一个指针来指向存储队列数据的空间,用两个变量来记录队列中存储数据的起始(对头)和末尾(队尾)的数组位置,最后用一个变量记录队列的存储数据的最大容量。
typedef struct {int *a;int front;int tail;int k;
} MyCircularQueue;
循环队列的初始化
循环队列的初始化首先创建一个循环队列,其次对该结构体的成员进行初始化即可。
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* cur=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));cur->a=(int *)malloc(sizeof(int)*(k+1));cur->k=k;cur->front=0;cur->tail=0;return cur;
}
注:k表示的是设置队列的长度
循环队列的入队列
入队列操作首先要判断循环队列是否已满,如果满了则返回假;如果没满则向循环队列插入一个数据(即在tail位置放数据)然后tail向后挪动一个位置,最后返回真。
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {assert(obj);if(myCircularQueueIsFull(obj)){return false;}obj->a[obj->tail]=value;obj->tail++;obj->tail=obj->tail%(obj->k+1);return true;
}
注:tail的位置为k+1时,就需要对tail进行处理防止tail对数组进行越界访问。这也遵循了循环队列的原则,当访问到数组末尾时再次访问应该访问到数组的起始位置。
循环队列的出队列
出队列操作首先判断循环队列是否为空,如果为空了,则出队列失败返回假;如果不为空则从循环队列中删除一个元素(即只需将front往后挪一个位置即可),如果成功删除则返回真。
bool myCircularQueueDeQueue(MyCircularQueue* obj) {assert(obj);if(myCircularQueueIsEmpty(obj)){return false;}obj->front++;obj->front%=obj->k+1;return true;
}
注:当front为k+1时处理方式和入队列的tail类似。
获取循环队列的对头数据
获取循环队列的对头数据首先判断循环队列是否为空,如果为空则返回-1;如果不为空只需通过front的位置获取数组中的数据并返回该数据即可。
int myCircularQueueFront(MyCircularQueue* obj) {assert(obj);if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[obj->front];
}
获取循环队列的对尾数据
获取循环队列的对尾数据首先判断循环队列是否为空,如果为空则返回-1;如果不为空只需通过tail获取tail的前一个位置的数组中的数据并返回该数据即可。
int myCircularQueueRear(MyCircularQueue* obj) {assert(obj);if(myCircularQueueIsEmpty(obj)){return -1;}int prevtail=obj->tail-1;if(obj->tail==0){prevtail=obj->k;}return obj->a[prevtail];
}
注:当tail为0时,此时取队尾数据时取的是数组下标为k的元素数据。因为tail表示的是最后一个有效数据的下一个位置。
循环队列的判空
循环队列的判空只需判断队头和队尾是否相等即可
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {assert(obj);return obj->front==obj->tail;
}
循环队列的判满
循环队列的判满只需判断队尾的下一个位置和队头是否相等即可
bool myCircularQueueIsFull(MyCircularQueue* obj) {assert(obj);return obj->front==((obj->tail)+1)%(obj->k+1);
}
注:当tail为k时tail的下一个位置为0,此时处理情况和出入队列的处理情况类似。
循环链表的销毁
循环链表的销毁首先要对循环链表结构体中的成员进行释放,然后再对循环链表进行释放即可。
void myCircularQueueFree(MyCircularQueue* obj) {assert(obj);free(obj->a);free(obj);obj=NULL;
}
注意:
- 环形队列中存储数据的空间是一开始就要创建好的,删除数据时是front指针往后走,存储数据的空间不销毁。插入数据时是往tail所指向的空间放数据,不申请空间,tail往后走。
- 循环队列如果用链表实现最好用双向链表实现,单向链表不好去找循环队列的队尾数据,而且采用链表的形式实现需要定义节点的结构体以及在初始化方面需要创建k+1个节点并建立连接,这样操作起来很麻烦没有数组省事,因此用数组实现循环队列更好。
相关文章:
数据结构—循环队列(环形队列)
循环队列(环形队列) 循环队列的概念及结构循环队列的实现 循环队列的概念及结构 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。…...
vue3 实现按钮权限管理
在做后台管理系统时,经常会有权限管理的功能,这里来记录一下关于按钮权限管理的实现方法 1、自定义指令 v-permission。新建js文件用来写指令代码。 export default function btnPerms(app) {app.directive(permission, {mounted(el, binding) {if (!p…...
C语言练习4(巩固提升)
C语言练习4 选择题 前言 面对复杂变化的世界,人类社会向何处去?亚洲前途在哪里?我认为,回答这些时代之问,我们要不畏浮云遮望眼,善于拨云见日,把握历史规律,认清世界大势。 选择题 …...
将AI融入CG特效工作流;对谈Dify创始人张路宇;关于Llama 2的一切资源;普林斯顿LLM高阶课程;LLM当前的10大挑战 | ShowMeAI日报
👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 将AI融入CG特效工作流,体验极致的效率提升 BV1pP411r7HY 这是 B站UP主 特效小哥studio 和 拓星研究所 联合投稿的一个AI特…...
Vue2学习笔记のVue中的ajax
目录 Vue中的ajaxvue脚手架配置代理方法一方法二 插槽 hello, 这篇文章是Vue2学习笔记的第四篇,也是第四章:Vue中的ajax。 Vue中的ajax vue脚手架配置代理 方法一 在vue.config.js中添加如下配置: devServer:{proxy:"http://localho…...
C# 使用NPOI操作EXCEL
1.添加NOPI 引用->管理NuGet程序包->添加NOPI 2.相关程序集 3....
分布式 - 服务器Nginx:一小时入门系列之 return 指令
文章目录 1. return 指令语法2. return code URL 示例3. return code text 示例4. return URL 示例 1. return 指令语法 return指令用于立即停止当前请求的处理,并返回指定的HTTP状态码和响应头信息,它可以用于在Nginx中生成自定义错误页面,…...
【Linux】ext4和xfs扩大,缩小lv后,无法识别如何操作
虚拟机系统异常,挂载到其他环境如何修复系统盘 1、环境 UOS 1060E x86环境 模拟异常环境: 1060e系统,使用lvm缩小磁盘后,出现异常,将异常磁盘挂载到其他服务器中,但存在问题发现有uuid相同的问题。 为…...
基于HarmonyOS ArkUI实现音乐列表功能
本节将演示如何在基于HarmonyOS ArkUI的List组件来实现音乐列表功能。 本文涉及的所有源码,均可以在文末链接中找到。 活动主页 华为开发者论坛 规则要求具体要求如下: 第1步:观看<HarmonyOS第一课>“营”在暑期•系列直播&#x…...
Android系统启动流程 源码解析
Android系统启动流程 本文链接:https://blog.csdn.net/feather_wch/article/details/132518105 有道云脑图:https://note.youdao.com/s/GZ9d8vzO 1、整体流程 Boot RoomBootLoaderidle kthreadinit init ServiceManagerzygote zygote SystemServerap…...
【头歌】构建哈夫曼树及编码
构建哈夫曼树及编码 第1关:构建哈夫曼树 任务描述 本关任务:构建哈夫曼树,从键盘读入字符个数n及这n个字符出现的频率即权值,构造带权路径最短的最优二叉树(哈夫曼树)。 相关知识 哈夫曼树的定义 设二叉树具有n个带权值的叶子结点{w1,w2,...,wn},从根结点到每个叶…...
创建本地镜像
通过前面文章的阅读,读者已经了解到所谓的容器实际上是在父镜像的基础上创建了一个可读写的文件层级,所有的修改操作都在这个文件层级上进行,而父镜像并未受影响,如果读者需要根据这种修改创建一个新的本地镜像,有两种…...
网络编程套接字(2): 简单的UDP网络程序
文章目录 网络编程套接字(2): 简单的UDP网络程序3. 简单的UDP网络程序3.1 服务端创建(1) 创建套接字(2) 绑定端口号(3) sockaddr_in结构体(4) 数据的接收与发送接收发送 3.2 客户端创建3.3 代码编写(1) v1_简单发送消息(2) v2_小写转大写(3) v3_模拟命令行解释器(4) v4_多线程版…...
Android Mvvm设计模式的详解与实战教程
一、介绍 在开发设计模式中,模式经历了多次迭代,从MVC到MVP,再到如今的MVVM。发现的过程其实很简单,就是为了项目更好的管理。 设计模式严格来说属于软件工程的范畴,但是如今在各大面试中或者开发中,设计模…...
软考A计划-系统集成项目管理工程师-小抄手册(共25章节)-下
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…...
渗透测试是什么?怎么做?
渗透测试报告 一、什么是渗透测试? 渗透测试是可以帮助用户对目前自己的网络、系统、应用的缺陷有相对直观的认识和了解。渗透测试尽可能地以黑客视角对用户网络安全性进行检查,对目标网络、系统和应用的安全性作深入的探测,发现系统最脆弱的…...
【软件安装】Python安装详细教程(附安装包)
软件简介 Python由荷兰数学和计算机科学研究学会的Guido van Rossum 于1990 年代初设计,作为一门叫做ABC语言的替代品。Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动态类型,以及解释型语言的本质,…...
微信小程序的form表单提交
获取input有两种方法: 第一:bindsubmit方法 注意: 1.使用form里面定义bindsubmit事件 2.bindsubmit事件需要配合button里面定义的formType“submit” 操作 3.设置input的name值来获取对应的数据 <form bindsubmit"formSubmit"…...
WOFOST模型与PCSE模型应用
实现作物产量的准确估算对于农田生态系统响应全球变化、可持续发展、科学粮食政策制定、粮食安全维护都至关重要。传统的经验模型、光能利用率模型等估产模型原理简单,数据容易获取,但是作物生长发育非常复杂,中间涉及众多生理生化过程&#…...
5-W806-RC522-SPI
main.c #include <stdio.h> #include "wm_hal.h" #include "rc522.h"int main(void) {SystemClock_Config(CPU_CLK_160M);printf("enter main\r\n");HAL_Init();RC522_Init();PcdReset();M500PcdConfigISOType ( A );//设置工作方式IC_te…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
