【数据结构】——环形队列

news2024/9/22 15:49:08

文章目录

  • 一.环形队列的定义及其特点
  • 二.使用数组来实现环形队列
    • 1.创建一个队列
    • 2.初始化队列
    • 3. 判断环形队列是否为空
    • 4.判断环形队列是否已满
    • 5. 向循环队列插入元素,插入成功返回真
    • 6.删除环形链表的数据
    • 7. 取队头元素
    • 8.取队尾元素
    • 8.释放空间
  • 总结



一.环形队列的定义及其特点

循环队列是一种线性数据结构,其操作依然是先进先出原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

特点:

对于一个普通队列来说,每出队一次,头指针就必须往后移一位,这样使用过的空间就无法再重复使用,(头指针无法回移),即使队列元素小于队列大小,也无济于事,造成空间的浪费。

而对于循环队列来说,可以重复利用使用过的空间。解决了普通队列的问题。

基于循环队列的特点:我们可以使用数组或者循环链表来实现循环队列。

使用数组实现的话,尾指针到数组的大小时,回溯到头位置即可。

在这里给出一道题来实现环形队列。
在这里插入图片描述

二.使用数组来实现环形队列

首先,需要了解清楚的一件事是:如何判断环形队列的数据是否为空或者是否满了?

假如创建一个大小为4的环形队列,判断环形队列是否为空很简单,如果头指针和尾指针相等,则队列是空的,因为如果插入数据,尾指针一定往后移动。

环形队列插满数据是这样的:
在这里插入图片描述
此时头指针和尾指针指向的位置也是相同的!

所以当队列满队的时候无法区分是队空还是队满。

解决办法:

假如环形队列大小是k,我们就创建k+1大小的环形队列。
在这里插入图片描述
只需判断 (tail+1)%(k+1)是否等于head 即可。

1.创建一个队列

解读:对于普通队列来说,需要头指针和尾指针来维护入队和出队操作,入队时尾指针后移,出队时头指针后移。
在环形队列中也是如此。

以下代码中的head和front是一样的。


typedef struct 
{
    int*a;
    int head;//队头
    int tail;//队尾,指向插入元素的下一个
    int k; //环形队列大小
} MyCircularQueue;

2.初始化队列

MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue*p = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    assert(p);
    p->a = (int*)malloc(sizeof(int)*(k+1));
    p->head = p->tail = 0;
    p->k = k; //环形队列大小
    return p;
}

开辟两块空间,一块空间是结构体的空间,一块空间是结构体的数组的空间。
在这里插入图片描述

3. 判断环形队列是否为空

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->head == obj->tail;
}

解读:环形队列是否为空就是判断头指针和尾指针是否相等,如果相等整个环形队列就为空,如果是其他情况,则环形队列至少有一个以上的数据。

4.判断环形队列是否已满

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    if((obj->tail+1)%(obj->k+1) ==obj->head)
    {
        return true;
    }
    return false;
}

判断环形队列是否已满,就是判断tail+1是否等于head,如果

5. 向循环队列插入元素,插入成功返回真

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
    {
        //满了
        return false;
    }
    obj->a[obj->tail] =value;
    //考虑特殊情况,如果插入之后tail是在外面,应该让tail回到0位置
    if(obj->tail+1 == obj->k+1) 
    {
        obj->tail = 0;
    }  
    else
    {
        ++obj->tail;
    }
    //也可以这样写
    // ++obj->tail;
    // obj->tail%=(obj->k+1);
    return true;
}

在这里插入图片描述

解读:

  1. 这里应该考虑的一种特殊情况是,假如插入的数据在环形队列的末尾,尾指针应该指向下一个位置,此时走出了数组的范围,所以需要回到数组0位置。
    2.如果环形队列满了,则不能再插入了。

6.删除环形链表的数据

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    //也是考虑特殊情况,如果删除后head在队列外面,则应让head回到0位置
    if(obj->head+1 == obj->k+1)
    {
        obj->head = 0;
    }
    else
    {
        ++obj->head;
    }
    //也可以这样写
    // ++obj->head;
    // obj->head%=obj->k+1;
    return true;
}
解读:
需要考虑特殊情况:特殊情况如下图:

在这里插入图片描述

7. 取队头元素

int myCircularQueueFront(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->a[obj->head];
}

8.取队尾元素

int myCircularQueueRear(MyCircularQueue* obj) {
    //取队尾元素有特殊情况,如果tail在0位置,那么需要返回
    //它的前一个,也就是第k个
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    if(obj->tail == 0)
    {
        return obj->a[obj->k];
    }
    else
    {
        return obj->a[obj->tail-1];
    }
    //也可以这样写
    //return (obj->tail+obj->k)%(obj->k+1);
}

取队尾元素有一种特殊情况:
在这里插入图片描述
假如tail是在0位置,取队尾元素之后,tail需要回退到上一个位
置,即k+1位置处。

8.释放空间

void myCircularQueueFree(MyCircularQueue* obj) {
    //注意结构体有两层,需要先释放内层
    free(obj->a);
    obj->a = NULL;
    free(obj);
}

总结

环形队列在普通队列的基础上优化了空间重复利用问题,使空间利用率更高。
实际生活中使用队列的问题还是有很多的,比如营业厅,医院,银行的自动排队出票的机子,也是通过队列的先进先出的特点来实现的。

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

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

相关文章

集算器连接外部库

1. 配置jar包将以下jar包从报表的类路径(【安装根目录】\report\lib或【安装根目录】\report\web\webapps\demo\WEB-INF\lib)中拷贝到集算器目录(【安装根目录】\esProc\ extlib\mongoCli);润乾外部库核心jar为:scu-mo…

AI制药 - TMScore(US-align)、RMSD、Sequence 源码

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/129125467 参考文档:Nature Methods | 蛋白、RNA、DNA及其复合物结构的比对算法US-align 官网地址:https://zhanggroup.org/US-align/ TMScore TMScore,…

【离散数学】2. 集合论

1.数理逻辑 2. 集合论 3. 代数系统 4. 图论 集合论:集合–>关系–>函数 n元组的理解:有n个集合,从每个集合中抽取一个元素,组成一个n元组 笛卡尔积的理解:笛卡尔积是n个集合能构成的所有互不相等的n元组的集合 …

软考考试真题精选

1、( )不属于项目范围说明书的内容A.项目的可交付成果 B.项目的假设条件 C.干系人清单 D.验收标准答案:C2、MPLS根据标记对分组进行交换,其标记中包含 ( ) 。…

使用maven搭建父子工程项目

创建父子工程,可以通过父工程来引入jar,定义统一的版本号等。更方便对整个项目的jar包实现统一化管理,让项目的层次更加清晰。一、创建父工程第一步:file–>new–>project–>maven默认使用jdk1.8,不引入任何j…

2.20计算机如何工作

一.计算机组成1.冯诺依曼体系CPU 中央处理器: 进行算术运算和逻辑判断.存储器: 分为外存和内存, 用于存储数据(使用二进制方式存储)输入设备: 用户给计算机发号施令的设备.输出设备: 计算机个用户汇报结果的设备内存和外存的区别(面试)访问速度:内存快,外存慢存储空间:内存小,外…

AI 看唇语,在嘈杂场景的语音识别准确率高达75%

事实上,研究表明视觉线索在语言学习中起着关键的作用。相比之下,人工智能语言识别系统主要是建立在音频上。而且需要大量数据来训练,通常需要数万小时的记录。 为了研究视觉效果,尤其是嘴部动作的镜头,是否可以提高语…

关于MySQL镜像构建过程中添加自动初始化数据库

需求描述一般而言,我们在拉取了 mysql 镜像并运行之后,其中的并不会存在我们自定义的数据库,都是在镜像运行后,自己主动导入数据库,那么有没有方式可以一运行 mysql 镜像,对应生成的 mysql 容器中就有我们自…

STM32 OTA应用开发——自制BootLoader

STM32 OTA应用开发——自制BootLoader 目录STM32 OTA应用开发——自制BootLoader前言1 环境搭建2 BootLoader工作原理以及常见分区介绍3 BootLoader的制作4 烧录下载配置5 运行测试结束语前言 什么是OTA? 百度百科:空中下载技术(Over-the-Ai…

【Java基础】IO流

IO流 最后一定要关闭流,防止资源泄露 字节流 一次读取1字节,8比特 FileInputStream import org.junit.jupiter.api.Test;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;public class CopyBytes {pub…

2023最新网络工程师面试大全,全都答得上offer绝对拿到手软

一、目录 TCP和UDP都可以实现客户端/服务端通信,这两个协议有何区别? 是第几层的协议,其作用是什么? 请说一下FTP,SSH,TELNET,DNS,HTTP,HTTPS,SMTP协议的端口…

我的三周年创作纪念日——学习不止,创作不停

机缘 最开始写文章博客,是为了用输出倒逼自己输入。 从校园离开后,才逐渐意识到学习的不容易。没有写好的教材课程、没有画好的考点重点,没有一起学习的同学,更没有明确的学习方向和路径。 数据分析方向可以学的东西太多了&…

SUMO安装并实现交通仿真Demo

sumo简介sumo是一种开源,微观,多模态的交通模拟仿真软件,每辆车都是明确建模的,有自己的路线,并在网络独立移动下载安装sumo前往sumo官网下载,如下图红色标注所示,一键安装。实现Demo3.1加载道路文件.net.x…

软件工程学习

文章目录前言软件特点分类软件工程软件危机项目管理工具总结前言 本博客仅做学习笔记,如有侵权,联系后即刻更改 科普: 软件 软件的定义 软件不是程序,而是程序、数据以及开发、使用和维护程序需要的所有文档的完整集合。 特点 …

100份简历才找一个合适的,2023,软件测试岗位饱和了吗?

各大互联网公司的接连裁员,政策限制的行业接连消失,让今年的求职雪上加霜,想躺平却没有资本,还有人说软件测试岗位饱和了,对此很多求职者深信不疑,因为投出去的简历回复的越来越少了。 另一面企业招人真的…

为什么启动一个线程不用run()方法,而是用start()方法

在使用java多线程时,有三种方式创建线程 复习传送门 当使用继承Thread来实现多线程时, 我们会把线程执行的代码写在run() 方法中, 使用Thread的start()方法来启动一个线程。 代码如下: public class ThreadDemo extends Thread{O…

RocketMQ快速入门:消息发送、延迟消息、消费重试

一起学编程,让生活更随和! 如果你觉得是个同道中人,欢迎关注博主gzh:【随和的皮蛋桑】。 专注于Java基础、进阶、面试以及计算机基础知识分享🐳。偶尔认知思考、日常水文🐌。 目录1、RocketMQ消息结构1.1…

算法训练营 day50 动态规划 单词拆分 多重背包理论基础

算法训练营 day50 动态规划 单词拆分 多重背包理论基础 单词拆分 139. 单词拆分 - 力扣(LeetCode) 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意:不要求字典中出现的单词…

佳能iC MF645CX彩色激光多功能打印机报E302-0001故障码检修

故障现象: 一台佳能iC MF645CX彩色激光多功能一体机开机报E302-0001故障代码,如果设备未恢复,请联系经销商或客户支持中心。 维修分析: 佳能iC MF645CX彩色激光多功能一体机开机报E302-0001故障代码的

java中NumberFormat 、DecimalFormat的介绍及使用,java数字格式化,BigDecimal数字格式化

文章目录前言一、NumberFormat1、概述2、实例化方法3、货币格式化4、百分比格式化5、NumberFormat的坑5.1、不同的格式化对象处理相同数值返回结果不同问题源码分析:二、DecimalFormat1、概述2、常用方法3、字符及含义0与#的区别分组分隔符的使用“%” 将数字乘以10…