数据结构—循环队列(环形队列)

循环队列(环形队列)

  • 循环队列的概念及结构
  • 循环队列的实现

循环队列的概念及结构

循环队列是一种线性数据结构,其操作表现基于 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个节点并建立连接,这样操作起来很麻烦没有数组省事,因此用数组实现循环队列更好。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用Cmake build OpenCV后,在VS中查看OpenCV源码的方法(环境VS2022+openCV4.8.0) Part II

用Cmake build OpenCV后,在VS中查看OpenCV源码的方法 Part II 用Cmake build OpenCV后,在VS中查看OpenCV源码的方法(环境VS2022openCV4.8.0) Part I_松下J27的博客-CSDN博客 在上一篇文章中,我用cmake成功的生成了ope…

设计模式三原则

1.1单一职责原则 C 面向对象三大特性之一的封装指的就是将单一事物抽象出来组合成一个类,所以我们在设计类的时候每个类中处理的是单一事物而不是某些事物的集合。 设计模式中所谓的单一职责原则,就是对一个类而言,应该仅有一个引起它变化的原…

我的128天创作纪念日-东离与糖宝

文章目录 机缘收获日常成就憧憬 不知不觉我也迎来了自己的128天创作纪念日,一起来看看我有什么想对大家说的吧 机缘 我的写博客之旅始于参加了代码随想录算法训练营。在训练营期间,代码随想录作者卡尔建议我们坚持每天写博客记录刷题学习的进度和心得体…

【LeetCode-中等题】240. 搜索二维矩阵 II

文章目录 题目方法一:暴力双for查找方法二:二分查找,对每二维数组进行拆分,一行一行的进行二分查找方法三:列倒序Z字形查找 题目 方法一:暴力双for查找 public boolean searchMatrix(int[][] matrix, int …

Java版B/S架构 智慧工地源码,PC、移动、数据可视化智慧大屏端源码

智慧工地是什么?智慧工地主要围绕绿色施工、安全管控、劳务管理、智能管理、集成总控等方面,帮助工地解决运营、管理方面各个难点痛点。在互联网的加持下促进项目现场管理的创新与发展,实现工程管理人员与工程施工现场的整合,构建…

系统架构师---软件重用、基于架构的软件设计、软件模型

目录 软件重用 构件技术 基于架构的软件设计 ABSD方法与生命周期 抽象功能需求 用例 抽象的质量和业务需求 架构选项 质量场景 约束 基于架构的软件开发模型 架构需求 需求获取 标识构件 需求评审 架构设计 架构文档 架构复审 架构实现 架构演化 前言&…

什么是响应式设计(Responsive Design)?如何实现一个响应式网页?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 响应式设计(Responsive Design)⭐ 如何实现一个响应式网页?1. 弹性网格布局2. 媒体查询3. 弹性图像和媒体4. 流式布局5. 优化导航6. 测试和调整7. 图片优化8. 字体优化9. 渐进增强10. 面向移动优先11. …

一、Kafka概述

目录 1.1 定义1.2 消息队列1、传统消息队列的应用场景2、消息队列的两种模式 1.3 Kafka的基础架构 1.1 定义 Kafka传 统定义:Kafka是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用于大数据实时处理领域。 K…

6、Spring_Junit与JdbcTemplate整合

Spring 整合 1.Spring 整合 Junit 1.1新建项目结构 1.2导入依赖 导入 junit 与 Spring 依赖 <!-- 添加 spring 依赖--> <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version…

数据结构数组栈的实现

Hello&#xff0c;今天我们来实现一下数组栈&#xff0c;学完这个我们又更进一步了。 一、栈 栈的概念 栈是一种特殊的线性表&#xff0c;它只允许在固定的一端进行插入和删除元素的操作。 进行数据的插入和删除只在栈顶实现&#xff0c;另一端就是栈底。 栈的元素是后进先出。…

前端高频面试题 js中堆和栈的区别和浏览器的垃圾回收机制

一、 栈(stack)和 堆(heap) 栈(stack)&#xff1a;是栈内存的简称&#xff0c;栈是自动分配相对固定大小的内存空间&#xff0c;并由系统自动释放&#xff0c;栈数据结构遵循FILO&#xff08;first in last out&#xff09;先进后出的原则&#xff0c;较为经典的就是乒乓球盒结…

验证码服务(使用提供好的项目)

1、先生成一个指定位数的验证码&#xff0c;根据需要可能是数字、数字字母组合或文字。 2、根据生成的验证码生成一个图片并返回给页面 3、给生成的验证码分配一个key&#xff0c;将key和验证码一同存入缓存。这个key和图片一同返回给页面。 4、用户输入验证码&#xff0c;连…

iPhone 15 Pro与谷歌Pixel 7 Pro:哪款相机手机更好?

考虑到苹果最近将更多高级功能转移到iPhone Pro设备上的趋势,今年秋天iPhone 15 Pro与谷歌Pixel 7 Pro的对决将是一场特别有趣的对决。去年发布的iPhone 14 Pro确实发生了这种情况,有传言称iPhone 15 Pro再次受到了苹果的大部分关注。 预计iPhone 15系列会有一些变化,例如切…

新版Jadx 加载dex报错 jadx.plugins.input.dex.DexException:Bad checksum 解决方法

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰,更不会影响计算机信息系统的正常运行。不得将代码用于非法用途,如侵立删!新版Jadx(1.6+) 加载dex报错 jadx.plugins.input.dex.DexException:Bad checksum 解决方法 环境 win10J…

QT5.12.12通过ODBC连接到GBase 8s数据库(CentOS)

本示例使用的环境如下&#xff1a; 硬件平台&#xff1a;x86_64&#xff08;amd64&#xff09;操作系统&#xff1a;CentOS 7.8 2003数据库版本&#xff08;含CSDK&#xff09;&#xff1a;GBase 8s V8.8 3.0.0_1 为什么使用QT 5.12.10&#xff1f;该版本包含QODBC。 1&#…

二进制数间按位逻辑运算按位逻辑与、逻辑或运算bitwise_and()bitwise_or()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 二进制数间按位逻辑运算 按位逻辑与、逻辑或运算 bitwise_and() bitwise_or() [太阳]选择题 下列代码最后一次输出的结果是&#xff1f; import numpy as np a, b 3, 8 print("…

Diffusion Models for Image Restoration and Enhancement – A Comprehensive Survey

图像恢复与增强的扩散模型综述 论文链接&#xff1a;https://arxiv.org/abs/2308.09388 项目地址&#xff1a;https://github.com/lixinustc/Awesome-diffusion-model-for-image-processing/ Abstract 图像恢复(IR)一直是低水平视觉领域不可或缺的一项具有挑战性的任务&…

【golang】for语句和switch语句

使用携带range子句的for语句时需要注意哪些细节&#xff1f; numbers1 : []int{1, 2, 3, 4, 5, 6} for i : range numbers1 {if i 3 {numbers1[i] | i} } fmt.Println(numbers1)这段代码执行后会打印出什么内容&#xff1f; 答案&#xff1a;[1 2 3 7 5 6] 当for语句被执行…

C++避坑——most vexing parse问题

1."坑"的问题是什么&#xff1f; 先看一段代码&#xff1a; class Functor { public:void operator()(){std::cout << "我是线程的初始函数" << std::endl;} };int main() {std::thread t(Functor());// 强制高速编译器这是一个构造函数!t.j…

智慧课堂学生行为检测评估算法

智慧课堂学生行为检测评估算法通过yolov5系列图像识别和行为分析&#xff0c;智慧课堂学生行为检测评估算法评估学生的表情、是否交头接耳行为、课堂参与度以及互动质量&#xff0c;并提供相应的反馈和建议。智慧课堂学生行为检测评估算法能够实时监测学生的上课行为&#xff0…