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

[C/C++]数据结构 循环队列

前言:

        队列是一种具有先进先出特性的结构,但是当数据出队列以后,前面的空间就无法再次利用了,循环队列就可以解决这个问题

一:概念及结构:

1.循环队列概念

        循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环.

2.循环队列结构

        循环队列可以使用数组实现也可以使用链表实现,但是还是建议使用数组实现.另外在给数组开辟空间时,要比队列实际长度多一个,如果开辟空间和队列存储数据的长度一样的话,在判断队列为空和队列为满时,两者都为 front==rear 会出现一样的情况导致无法判断,如

所以必须多开辟一个空间,这个空间不存储数据,这样就可以区分出两种情况

结构定义:

        front用于维护队头,指向队头元素位置,back用于维护队尾,总是指向队尾元素的下一个位置,k表示队列实际存数据的长度

ps:循环队列的长度是固定的

typedef struct {int *a;int front; int back;int k;  //队列大小
} MyCircularQueue;

二:功能实现

1.入队:

    首先要判断队列是否已满,再进行入队的操作,入队操作需要考虑索引循环的问题,当索引越界,需要让它变成最小值

        如果入队是这种情况,直接在队尾处插入数据,back++即可

        但是如果碰到这种情况,back就不能简单加一就完事了了,还需要将back重新指向数组刚开始的空间,不然就体现不出循环的特点了

         所以在队尾插入数据back++后,进行 back=(back)%(k+1) 就可以使back重新指向数组起始位置(这里要注意的是,我定义的k是队列不带多开辟的那一个空间的长度)

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj))//入队前先判断是否还有空间return false;obj->a[obj->back]=value;obj->back++;obj->back%=(obj->k+1);return true;
}

2.出队:

       首先判断队列是否为空,在进行出队操作,出队也需要考虑front的索引问题

bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return false;obj->front++;obj->front%=(obj->k+1);return true;
}

3.取队头元素

        front指向的就是队头元素

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

4.取队尾元素

          由于back始终指向队尾的下一个元素,在一般情况下直接返回back-1所指向的元素即可,但是有一种特殊情况,如果此时back指向的是数组起始位置的话,访问back-1所指向的元素就会越界,所以这里也涉及循环的问题

方法一: 把特殊情况分离出来

int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;if(obj->back==0)return obj->a[obj->k];elsereturn obj->a[obj->back-1];
}

方法二: 两种情况统一处理

int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj))return -1;return obj->a[(obj->back-1+obj->k+1)%(obj->k+1)];
}

5.判空

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front==obj->back;
}

6.判满

bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->back+1)%(obj->k+1)==obj->front;
}

7.销毁队列

void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);obj->front=obj->back=0;obj->k=0;
}

8.求队列当前元素个数

当back在front之后时,back-front就可获得当前队列元素个数,但是当back在front前面时,back+(k+1)

可以让back指向不处理循环问题本身应该指向的位置

int myCircularQueueSize(MyCircularQueue* obj) {return (obj->back+(k+1)-obj->front)%(k+1);
}

相关文章:

  • springboot(ssm付费自习室管理系统 自习室预约平台Java(codeLW)
  • Hive csv文件导入Hive
  • SpringBoot 2 系列停止维护,Java8 党何去何从?
  • java - 定时器
  • 领域驱动设计总结——如何构造领域模型
  • video标签在h5中被劫持问题
  • R语言数据缩放-1到1
  • ElasticSearch之cat component templates API
  • 【JavaEE】多线程 (2) --线程安全
  • 【Docker】从零开始:6.配置镜像加速器
  • 超实用!Spring Boot 常用注解详解与应用场景
  • 一、用户管理
  • 【Java】循环语句练习
  • MIT 6.S081学习笔记(第三章)
  • 在vue或者react或angular中,模板表达式中的箭头函数是无效的吗?为什么无效?
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • CSS 三角实现
  • JAVA并发编程--1.基础概念
  • Js基础——数据类型之Null和Undefined
  • laravel 用artisan创建自己的模板
  • MySQL QA
  • Puppeteer:浏览器控制器
  • Python socket服务器端、客户端传送信息
  • Sass Day-01
  • Spark学习笔记之相关记录
  • spring security oauth2 password授权模式
  • 程序员该如何有效的找工作?
  • 关于Flux,Vuex,Redux的思考
  • 缓存与缓冲
  • 前端自动化解决方案
  • 如何设计一个比特币钱包服务
  • 使用agvtool更改app version/build
  • No resource identifier found for attribute,RxJava之zip操作符
  • Hibernate主键生成策略及选择
  • Semaphore
  • 交换综合实验一
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #AngularJS#$sce.trustAsResourceUrl
  • #Z2294. 打印树的直径
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (规划)24届春招和25届暑假实习路线准备规划
  • (南京观海微电子)——COF介绍
  • (篇九)MySQL常用内置函数
  • (转)shell调试方法
  • (转)创业家杂志:UCWEB天使第一步
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET CLR基本术语
  • .Net CoreRabbitMQ消息存储可靠机制
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .NET多线程执行函数
  • .NET开发不可不知、不可不用的辅助类(一)
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .ui文件相关