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

【数据结构与算法(C语言)】循环队列图解

目录

  • 1. 前言
    • 1.1 普通循环队列假溢出
      • 1.1.1 初始化队列
      • 1.1.2 插满队列
      • 1.1.3 删除元素后,再插入元素
    • 1.2 循环队列
      • 1.2.1 插入元素,队列已满
      • 1.2.2 将元素J1、J2出列,循环队列又空出两个空间
      • 1.2.3 元素J6可以继续入列
  • 2. 存储结构和函数说明
    • 2.1 队列的结构
    • 2.2 基本操作函数
    • 2.3 初始化队列
    • 2.4 销毁队列 DestroyQueue
    • 2.5 清空队列 ClearQueue
    • 2.6 获取队列第一个元素 GetHead
    • 2.7 获取队列长度
    • 2.8 元素入列 EnQueue
    • 2.9 元素出列 DeQueue
    • 2.10 遍历队列 QueueTraverse
  • 3. 完整源码和测试代码
  • 4. 测试结果
  • 5. 小结
    • 5.1 优点:
    • 5.2 缺点

1. 前言

将队列的头尾相接,臆造成环状的顺序存储结构称为循环队列

普通的顺序存储队列会出现 假溢出 情况。如下面三张图(三个步骤)描述的情况

1.1 普通循环队列假溢出

下面来看看普通队列是如何产生假溢出现象的。

1.1.1 初始化队列

此时队列为空队列。头指针和尾指针都指向第一个空间
空队列

1.1.2 插满队列

插入J1、J2、J3、J4、J5、J6,因为q->rear=6,说明队列已满
在这里插入图片描述

1.1.3 删除元素后,再插入元素

删除J1,J2,按道理应该是空出两个空间,可以插入新元素,但此时q ->rear指向6号地址,还是判定队列已满,如果再插入元素,q-rear=7,则队列溢出。但实际队列是有空间的

在这里插入图片描述

1.2 循环队列


普通的循环队列有上述假溢出缺点。于是乎,循环队列就应运而生了。


循环队列的解决假溢出方法 如下面三张图中展示的步骤:

1.2.1 插入元素,队列已满

还剩一个空间的时候,队列就满了。这样设置的原因是,如果不浪费一个空间的话,当 queue.front=queue.rear,可能会有两种情况,一个是队列为空,一个是队列已满。如果预留一个空间的话,可以用 queue.rear + 1=queue.front 判断队列已满,这样和队列为空的判断方式不冲突。
在这里插入图片描述

1.2.2 将元素J1、J2出列,循环队列又空出两个空间

在这里插入图片描述

1.2.3 元素J6可以继续入列

在这里插入图片描述

2. 存储结构和函数说明

2.1 队列的结构

typedef struct{QElemType * base;  //存储空间 int front;	   //队列头的下标int rear; 	   //队列尾的下标
}SqQueue;     //定义一个队列类型 

2.2 基本操作函数

和上一篇博客中的链式队列差不多,一共8个函数。

Status InitQueue(SqQueue * queue); //初始化队列
void DestroyQueue(SqQueue *queue); //销毁队列
Status ClearQueue(SqQueue * queue);//清空队列
Status QueueEmpty(SqQueue queue);  //判断队列是否为空
Status GetHead(SqQueue queue ,QElemType * e); //获取队列头元素
int QueueLength(SqQueue queue);			//获取队列长度
Status EnQueue(SqQueue  * queue, QElemType e); //元素入列
Status DeQueue(SqQueue * queue ,QElemType * e); //元素出列

2.3 初始化队列

原型:Status InitQueue(SqQueue * queue)
说明:初始化队列,申请一个头结点的内存

/*初始化队列,申请一个头结点的内存*/
Status InitQueue(SqQueue * queue)
{queue->base = (QElemType *) malloc(sizeof(QElemType)*MAXSIZE); //申请一个队列结点作为头结点的内存地址给 队头指针;if(queue->base == NULL)return FALSE;queue->front = queue->rear =0;return TRUE;
}

2.4 销毁队列 DestroyQueue

原型 :void DestroyQueue(SqQueue *queue)
功能 :销毁队列,释放队列的数据空间

/*销毁栈,释放队列的数据空间*/
void DestroyQueue(SqQueue *queue)
{free(queue->base);queue->front= queue->rear =0;
}

2.5 清空队列 ClearQueue

原型:Status ClearQueue(SqQueue * queue)
功能 :清空队列的元素,但队列的空间保留

//将队列queue清空
Status ClearQueue(SqQueue * queue)
{queue->front = queue->rear = 0;return OK;	
}

2.6 获取队列第一个元素 GetHead

原型:Status GetHead(SqQueue queue ,QElemType * e)
功能 :获取队列第一个元素,注意 不是删除元素

//获取队列第一个元素
Status GetHead(SqQueue queue ,QElemType * e)
{if(QueueEmpty(queue))return FALSE;*e=queue.base[queue.front];return TRUE;
}

2.7 获取队列长度

原型:int QueueLength(SqQueue queue)
功能 :队列长度

//返回队列长度
int QueueLength(SqQueue queue)
{return (queue.rear - queue.front + MAXSIZE) % MAXSIZE;
}

2.8 元素入列 EnQueue

原型:Status EnQueue(SqQueue * queue, QElemType e)
功能 :元素e 插入队列queue

//元素e 插入队列queue
Status EnQueue(SqQueue  * queue, QElemType e)
{if((queue->rear + 1) % MAXSIZE == queue->front) //队列满,return FALSE ;queue->base[queue->rear]=e;       //e 插入队列尾部,队尾加1queue->rear = (queue->rear + 1) % MAXSIZE;return TRUE;
}

2.9 元素出列 DeQueue

原型:Status DeQueue(SqQueue * queue ,QElemType * e)
功能 :若队列queue不空,则删除Q的队头元素,用e返回其值,并返回 OK;否则返回ERROR

//若队列queue不空,则删除Q的队头元素,用e返回其值,并返回 OK;否则返回ERROR
Status DeQueue(SqQueue * queue ,QElemType * e)
{if(QueueEmpty( *queue))return FALSE;*e = queue->base[queue->front];queue->front= (queue->front + 1) % MAXSIZE;return TRUE;
}

2.10 遍历队列 QueueTraverse

原型:Status QueueTraverse(SqQueue queue,void (*visit)())
功能 :遍历队列,对队列的每个元素调用Visit函数

//遍历队列,对队列的每个元素调用Visit函数
Status QueueTraverse(SqQueue queue,void (*visit)())
{int i = queue.front;if(QueueEmpty(queue))return FALSE ;if(queue.front < queue.rear)	while(i < queue.rear)visit(queue.base[i++]);else{while(i< MAXSIZE)visit(queue.base[i++]);i=0;while(i<queue.rear)visit(queue.base[i++]);}return TRUE;
}

3. 完整源码和测试代码

#include <stdio.h>
#include <stdlib.h>#define TRUE  1
#define FALSE 0
#define OK    1
#define ERROR 0
#define MAXSIZE 6 //最大值设置为6typedef  int Status;typedef  int QElemType; //定义元素类型为整型typedef struct{QElemType * base;  //存储空间 int front;	   //队列头的下标int rear; 	   //队列尾的下标
}SqQueue;     //定义一个队列类型 Status InitQueue(SqQueue * queue);
void DestroyQueue(SqQueue *queue);
Status ClearQueue(SqQueue * queue);
Status QueueEmpty(SqQueue queue);
Status GetHead(SqQueue queue ,QElemType * e);
int QueueLength(SqQueue queue);
Status EnQueue(SqQueue  * queue, QElemType e);
Status DeQueue(SqQueue * queue ,QElemType * e);/*初始化队列,申请一个头结点的内存*/
Status InitQueue(SqQueue * queue)
{queue->base = (QElemType *) malloc(sizeof(QElemType)*MAXSIZE); //申请一个队列结点作为头结点的内存地址给 队头指针;if(queue->base == NULL)return FALSE;queue->front = queue->rear =0;return TRUE;
}/*销毁队列,释放队列的数据空间*/
void DestroyQueue(SqQueue *queue)
{free(queue->base);queue->front= queue->rear =0;
}//将队列queue清空
Status ClearQueue(SqQueue * queue)
{queue->front = queue->rear = 0;return OK;	
}//判断队列是否为空
Status QueueEmpty(SqQueue queue)
{return queue.front == queue.rear? TRUE:FALSE; 
}//获取队列第一个元素
Status GetHead(SqQueue queue ,QElemType * e)
{if(QueueEmpty(queue))return FALSE;*e=queue.base[queue.front];return TRUE;
}//返回队列长度
int QueueLength(SqQueue queue)
{return (queue.rear - queue.front + MAXSIZE) % MAXSIZE;
}//元素e 插入队列queue
Status EnQueue(SqQueue  * queue, QElemType e)
{if((queue->rear + 1) % MAXSIZE == queue->front) //队列满,return FALSE ;queue->base[queue->rear]=e;       //e 插入队列尾部,队尾加1queue->rear = (queue->rear + 1) % MAXSIZE;return TRUE;
}//若队列queue不空,则删除Q的队头元素,用e返回其值,并返回 OK;否则返回ERROR
Status DeQueue(SqQueue * queue ,QElemType * e)
{if(QueueEmpty( *queue))return FALSE;*e = queue->base[queue->front];queue->front= (queue->front + 1) % MAXSIZE;return TRUE;}
void Visit(QElemType e)
{printf("%3d",e);
}
//遍历队列,对队列的每个元素调用Visit函数
Status QueueTraverse(SqQueue queue,void (*visit)())
{int i = queue.front;if(QueueEmpty(queue))return FALSE ;if(queue.front < queue.rear)	while(i < queue.rear)visit(queue.base[i++]);else{while(i< MAXSIZE)visit(queue.base[i++]);i=0;while(i<queue.rear)visit(queue.base[i++]);}return TRUE;
}int main()
{QElemType e;SqQueue queue;InitQueue(&queue);printf("队头分别插入数字3、4、5、6、7后:");//此时队列已经满了,设置maxsize=6,实际只能存储5个,//因为只剩一个空间,代表队列已满。即 front= (rear+1)%maxsize//如果不留一个空间空着,那么队列满和队列空都是 front=rear,很难分辨EnQueue(&queue,3);EnQueue(&queue,4);EnQueue(&queue,5);EnQueue(&queue,6);EnQueue(&queue,7);QueueTraverse(queue,Visit);printf("\n继续插入数字8");if(EnQueue(&queue,8))printf("\n出问题了,队列满了,还能插入!");elseprintf("\n队列已满,无法插入!");printf("\n删除队头数字后:");DeQueue(&queue,&e);	    //删除后的队列中还剩4个元素QueueTraverse(queue,Visit);printf("\n继续插入8数字后:");EnQueue(&queue,8);	    //数字8被存放到queue.base[5]中了QueueTraverse(queue,Visit);printf("\n清空队列");ClearQueue(&queue);printf("\n队列长度:%d\n",QueueLength(queue));DestroyQueue(&queue);getchar();return 0;
}

4. 测试结果

在这里插入图片描述

5. 小结

循环队列的优缺点

5.1 优点:

(a) 解决了普通的顺序存储队列的假溢出问题。
(b) 读取方便、快捷

5.2 缺点

存储空间大小固定,无法根据需要进行扩展。

相关文章:

【数据结构与算法(C语言)】循环队列图解

目录 1. 前言1.1 普通循环队列假溢出1.1.1 初始化队列1.1.2 插满队列1.1.3 删除元素后&#xff0c;再插入元素 1.2 循环队列1.2.1 插入元素&#xff0c;队列已满1.2.2 将元素J1、J2出列&#xff0c;循环队列又空出两个空间1.2.3 元素J6可以继续入列 2. 存储结构和函数说明2.1 队…...

私域流量转化不济的原因

你是不是也曾感到私域流量的转化一直不如意&#xff1f;让我来告诉你&#xff0c;这六大问题是为什么&#xff0c;以及如何轻松解决它们&#xff0c;提升你的私域流量转化率&#xff01; 1. 问题&#xff1a;目标不明确 你是否常常感到茫然&#xff0c;不知道私域流量应该有何目…...

百万上下文RAG,Agent还能这么玩

❝ 在AI技术飞速发展的今天&#xff0c;我们见证了许多令人惊叹的突破。最近&#xff0c;Qwen2模型的开源引起了广泛的关注&#xff0c;它不仅展示了超越闭源模型的能力&#xff0c;还带来了一个全新的框架——Qwen-Agent。 Qwen-Agent的设计思路虽然与LangChain相似&#xff0…...

【后端开发】服务开发场景之高可用(冗余设计,服务限流,降级熔断,超时重试,性能测试)

【后端开发】服务开发场景之高可用&#xff08;冗余设计&#xff0c;服务限流&#xff0c;降级熔断&#xff0c;超时重试&#xff0c;性能测试&#xff09; 文章目录 序&#xff1a;如何设计一个高可用的系统&#xff1f;可用性的判断指标是什么&#xff1f;哪些情况会导致系统…...

在 Selenium 中更改 User-Agent | 步骤与最佳实践

在 Selenium 中更改 User Agent 是许多网页抓取任务中的关键步骤。它有助于将自动化脚本伪装成常规浏览器&#xff0c;从而避免被网站检测到。本指南将带您了解如何在 Selenium 中更改 Google Chrome 的 User Agent&#xff0c;并提供最佳实践以确保您的网页抓取任务顺利进行。…...

2024酒店IPTV云桌面系统建设方案

Hello大家好&#xff0c;我是点量小芹&#xff0c;这一年多的时间一直在分享实时云渲染像素流相关的内容&#xff0c;今天和大家聊聊酒店IPTV云桌面电视系统解决方案&#xff0c;或者有的朋友也会称之为IPTV服务器。熟悉小芹的朋友知道&#xff0c;IPTV软件系统是我们一直在推的…...

java Thrift TThreadPoolServer 多个processor 的实现

当我们使用Thrift 通信的时候&#xff0c;服务端有时候需要注册多个类&#xff0c;去实现通信&#xff0c;这时候我们就不能再使用单一Processor的方式&#xff0c;就要使用多个Processor&#xff0c;那么如何去实现呢&#xff1f; 多个Process 服务端 public static void m…...

失眠焦虑的解脱之道:找回内心的平静

&#x1f343; 在这个快节奏的时代&#xff0c;失眠与焦虑似乎成了许多人的隐形敌人。每当夜幕降临&#xff0c;它们便悄悄潜入心底&#xff0c;扰乱我们的思绪&#xff0c;让宁静的夜晚变得无比漫长。然而&#xff0c;生活总有办法让我们找回内心的平静&#xff0c;只需稍作调…...

OLED柔性屏的显示效果如何

OLED柔性屏的显示效果非常出色&#xff0c;具有多方面的优势。以下是关于OLED柔性屏显示效果的详细分析&#xff1a; 色彩表现&#xff1a;OLED柔性屏的每个像素都可以独立发光&#xff0c;因此色彩准确性极高。黑色呈现得非常深邃&#xff0c;而亮部则展现出鲜明而生动的细节。…...

百货商城优选 伊利牛奶推出全国首款减甲烷环保学生奶

近日&#xff0c;伊利集团受邀参加在全国首个“国际首脑峰会零碳场馆”召开的“降碳增产科技助力奶业绿色高质量发展”首款低碳饲料创新大会。会上&#xff0c;伊利宣布将推出全国首款减甲烷环保学生牛奶——伊利QQ星学生纯牛奶&#xff0c;进一步将可持续发展落到实处&#xf…...

Fluid 1.0 版发布,打通云原生高效数据使用的“最后一公里”

作者&#xff1a;顾荣 前言 得益于云原生技术在资源成本集约、部署运维便捷、算力弹性灵活方面的优势&#xff0c;越来越多企业和开发者将数据密集型应用&#xff0c;特别是 AI 和大数据领域应用&#xff0c;运行于云原生环境中。然而&#xff0c;云原生计算与存储分离架构虽…...

软件测试--第十一章 设计和维护测试用例

1.单选题 (2分) 下面有关测试设计的叙述,说法不正确的是( )。 A 测试用例的设计是一项技术性强.智力密集型的活动 B 在开展测试用例设计前,必须将测试需求进行详细展开 C 在一般的测试组织内,测试用例的评审可能不是正式的评审会 D 在测试用例设计时,只设计覆盖正常流程和操…...

前端只允许一次函数调用

如果你正在进行前端开发&#xff0c;并且只想允许一次函数调用&#xff0c;你可以使用JavaScript的闭包结构创建一个只能被调用一次的函数。这样的函数有时被称为单次调用函数&#xff08;“one-time call” functions&#xff09;或一次性函数&#xff08;“once” functions&…...

visdom使用时所遇的问题及解决方法

最近在用visdom进行可视化的过程中&#xff0c;虽然可有效的避免主机拒绝访问&#xff08;该问题的解决方法&#xff0c;请参考深度学习可视化工具visdom使用-CSDN博客&#xff09;即在终端输入python -m visom.server 1.训练过程中visdom出现ValueError: too many file descr…...

密封类(sealed class)

在 Kotlin 中&#xff0c;密封类&#xff08;sealed class&#xff09;是一种受限的类层次结构&#xff0c;允许您定义一个封闭的类层次结构&#xff0c;其中类的所有可能子类都已知并且位于同一文件中。密封类的主要作用是提供类型安全的受限层次结构&#xff0c;使得 when 表…...

私域引流宝PHP源码 以及搭建教程

私域引流宝PHP源码 以及搭建教程...

磁盘管理 以及磁盘的分区 详细版

磁盘管理 track:磁道&#xff0c;就是磁盘上同心圆&#xff0c;从外向里&#xff0c;依次1号、2号磁道sector&#xff1a;扇区&#xff0c;将磁盘分成一个一个扇形区域&#xff0c;每个扇区大小是512字节&#xff0c;从外向里&#xff0c;依次是1号扇区、2号扇区cylinder&…...

加码多肤色影像技术 这是传音找到的“出海利器“?

全球化时代&#xff0c;市场竞争愈演愈烈&#xff0c;产品差异化已然成为了企业脱颖而出的关键。在黄、白肤色长期占据人像摄影主赛道的背景下&#xff0c;传音就凭借独一无二的多肤色影像技术走出非洲&#xff0c;走向了更广阔的新兴市场。 聚焦深肤色人群拍照痛点&#xff0c…...

C++方法封装成dll及C#调用示例

1,编译生成dll时可能出现错误&#xff0c;解决办法&#xff1a;pch.h文件头部&#xff0c;添加声明 #define _CRT_SECURE_NO_WARNINGS 2, c头文件声明 extern "C" __declspec(dllexport) char* getvalue(const char * param1, const char * param2); 3, c方法实现…...

定时清理Linux服务器缓存shell脚本

服务器内存占用过高,如何定时清理一下服务器内存呢?写一个清理缓存脚本,加入到定时任务中。 一、编写脚本 clear_cache.sh 脚本,放到home目录下。 #!/bin/bash# 清除页面缓存、目录项和 inode 缓存 sudo sync echo 3 | sudo tee /proc/sys/vm/drop_caches# 记录执行时间到日…...

Guava常用方法

目录 一、数学和数值操作 二、并发库 三、缓存 四、集合 五、I/O 与文件操作 六、网络 七、时间处理 八、事件总线 九、反射 十、范围和集合操作 十一、随机数和测试 十二、注解处理 十三、比较器和排序 十四、哈希和散列 Guava 是 Google 开源的一个 Java 工具库&#xff…...

干货分享:宏集物联网HMI通过S7 MPI协议采集西门子400PLC数据

前言 为了实现和西门子PLC的数据交互&#xff0c;宏集物联网HMI集成了S7 PPI、S7 MPI、S7 Optimized、S7 ETH等多个驱动来适配西门子200、300、400、1200、1500、LOGO等系列PLC。 本文主要介绍宏集HMI通过S7 MPI协议采集西门子400PLC数据的操作步骤&#xff0c;其他协议的操作…...

【Web API DOM11】节点操作

目录 一&#xff1a;DOM节点 1 什么是DOM节点 2 DOM节点分类 二&#xff1a;节点查找&#xff08;元素节点&#xff09; 1 节点关系 父节点 子节点 兄弟节点 三&#xff1a;增加节点 1 创建节点 2 追加节点 2 案例&#xff1a;渲染数据 案例中核心代码块 样式 四…...

Unity 设置窗口置顶超级详解版

目录 前言 一、user32.dll 1.什么是user32.dll 2.如何使用user32.dll 二、句柄Handle 1.句柄 2.句柄的功能 3.拿句柄的方法 三、窗口置顶 1.窗口置顶的方法 2.参数说明 3.使用方法 四、作者的碎碎念 前言 up依旧挑战全网讲解最详细版本~~ 本篇文章讲解的是unity…...

编程后端:深入探索其所属的行业领域

编程后端&#xff1a;深入探索其所属的行业领域 在数字化浪潮席卷全球的今天&#xff0c;编程后端作为技术领域的重要分支&#xff0c;其所属的行业领域一直备受关注。本文将从四个方面、五个方面、六个方面和七个方面&#xff0c;深入剖析编程后端所属的行业&#xff0c;并揭…...

ubuntu18.04离线源制作

给客户部署有时需要纯内网环境&#xff0c;那这样就连不了网络。 一些包就下载不下来&#xff0c;而大家都知道用deb离线安装是非常麻烦的&#xff0c;各种依赖让你装不出来。 这里教大家打包源。 我准备2台机器&#xff0c;42和41 42可以联网&#xff0c;41不能联网。我想在…...

【DPDK学习路径】八、轮询

前面我们已经了解了如何使用DPDK创建线程并绑定核心&#xff0c;以及如何申请内存池并创建 RX/TX 队列。 接下来我们将了解DPDK的核心内容之一&#xff1a;以轮询的方式从网卡中收取报文。 下面直接给出一个实例&#xff0c;此实例使用核心1及核心2创建了两个线程用于报文处理&…...

Mac环境下,简单反编译APK

一、下载jadx包 https://github.com/skylot/jadx/releases/tag/v1.4.7 下载里面的这个&#xff1a;下载后&#xff0c;找个干净的目录解压&#xff0c;我是放在Downloads下面 二、安装及启动 下载和解压 jadx&#xff1a; 下载 jadx-1.4.7.zip 压缩包。将其解压到你希望的目…...

027、工具_redis-benchmark

redis-benchmark可以为Redis做基准性能测试 1.-c -c(clients)选项代表客户端的并发数量(默认是50)。 2.-n -n(num)选项代表客户端请求总量(默认是100000)。 例如redis-benchmark-c100-n20000代表100各个客户端同时请求Redis,一 共执行20000次。 redis-benchmark会…...

京准电钟 | 对比GPS,北斗卫星授时的场景有哪些?

京准电钟 | 对比GPS&#xff0c;北斗卫星授时的场景有哪些&#xff1f; 京准电钟 | 对比GPS&#xff0c;北斗卫星授时的场景有哪些&#xff1f; 对比国外的GPS&#xff0c;我国北斗卫星授时由于其高精度和稳定性&#xff0c;在各个领域都有广泛的应用场景。 以下是一些单北斗卫…...