设计循环队列(详解)

呀哈喽,我是结衣
今天给大家带来的内容如标题所述,我们来设计环形队列,虽然队列没有讲,但是我就是想讲啊。那么环形队列现在开始。

队列的属性

在设计环形队列前,我们先要了解队列的特点(先进先出),就想现实中我们排队一样,先到的人先得。所以现实中银行的取票机是可以用队列实现的。

循环队列

本次讲解是基于leetcode的以题来讲解的,贴张图给大家介绍吧:
在这里插入图片描述
看完题目不知道大家有没有思路呢?没有的话就听我详细的解释吧。

顺序表or链表

看完题目你最先想到的实现方法是顺序表还是链表呢?倒不是说这两种方法只能选择一个,而是实现难易程度问题,你觉得用顺序表难还是用链表难呢?这里我选择用顺序表来讲解,我觉得顺序表简单一些呢。

顺序表实现循环队列

在实现之前我们来看看题目要我们实现的功能吧:

typedef struct {} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {}bool myCircularQueueDeQueue(MyCircularQueue* obj) {}int myCircularQueueFront(MyCircularQueue* obj) {}int myCircularQueueRear(MyCircularQueue* obj) {}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {}bool myCircularQueueIsFull(MyCircularQueue* obj) {}void myCircularQueueFree(MyCircularQueue* obj) {}

在这里插入图片描述
了解完要求下面我们就要分析了。

怎样实现循环

首先我们要定义一个头和尾。(front和back)他们就是下标哈。
有了头和尾。我们要把他们的初始值给多少呢,都给‘0’还是给‘-1’呢,这里我的做法是把头和尾都给‘0’,你可能会说那如果插入了一个数,back怎么办。哼哼,我们把back++,我们让back指向的最后一个数的下一个,而非最后一个数,那么新的问题又来了,当出现这种情况怎么办。
在这里插入图片描述
back不就出去了吗,是的,我们要解决这个问题就要多定义一个空间,题目让我们定义k个空间,我们就要定义k+1个空间。但是有一个空间是不存储数据的。
在这里插入图片描述
在k+1个空间中始终有一个空间是不存储数据的只有这样才能满足题目要求的k个空间。
在这里插入图片描述
这就是循环的示意图,当前面有空间,又要插入数据时,在back的位置上插入数据后再将back = 0。

结构体的创建

typedef struct {int* data;int front;int back;int k;
} MyCircularQueue;

相信看完上面的简介这个结构体的创建是没有问题的吧。

函数的实现

这里的函数的实现并不是按照题目顺序来进行的。因为这里的函数也可以相互的调用为后续节省时间。

初始化

MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* tmp = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));tmp->data = (int*)malloc(sizeof(int) * (k + 1));tmp->front = 0;tmp->back = 0;tmp->k = k;return tmp;
}

我们先要malloc一个结构体的空间,然后再malloc tmp->data这个数组的大小,因为我们有一个空位置所以就开了k+1个的空间。还有头和尾的赋值尾‘0’,在上面的实现循环里有讲解。

队列判空

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

这个代码就很直观了,back == front就直接判空了。因为我们这里的back是不会有数据的,出现这种情况这样最初的时候在那种情况就是队列为空的情况。

队列判满

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

我们都知道当back的下一个为front的时候就是满的时候,所以写成back+1 == front是不是就可以了呢?不是不行,多加个判断就可以了,但是为我们要介绍的方法取余的方法,在这种循环中就特别的好用,利用的就是当被除数比除数小的时候余数为被除数。

数据插入

写完判空判满的函数,我们下面就会轻松一些
要插入数据我们首先就是要判断队列有没有满,如果满了就不能插入,并且返回false

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if (myCircularQueueIsFull(obj)){return false;}obj->data[obj->back] = value;if (obj->back == obj->k)obj->back = 0;elseobj->back++;return true;
}

除了判满,我们还要小心当back在最后的情况下,在最后的话如果我们还是back++的话,back就出界了,后果可是很严重的,后面返回为数据的时候就可能会访问野指针。导致程序崩溃。所以我们就要加判断呢。

数据删除

删除数据的时候我们要知道队列不能为空,为空就不能删除,返回false。

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

当然后面判断和前面插入的时候相似,front在最后的时候就不能++了,要让他等于0。

返回头

不能为空

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

返回尾

不能为空的同时还要注意,back为0的时候,如果你还 减减 不久变成负数了吗,这样肯定是不行的,所以我们要再加一个判断咯。

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

销毁

void myCircularQueueFree(MyCircularQueue* obj) {free(obj);obj = NULL;
}

销毁就是十分的简单

循环队列代码

typedef struct {int* data;int front;int back;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* tmp = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));tmp->data = (int*)malloc(sizeof(int) * (k + 1));tmp->front = 0;tmp->back = 0;tmp->k = k;return tmp;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj) {if (obj->back == obj->front){return true;}return false;
}bool myCircularQueueIsFull(MyCircularQueue* obj) {if ((obj->back + 1) % (obj->k + 1) == obj->front){return true;}return false;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if (myCircularQueueIsFull(obj)){return false;}obj->data[obj->back] = value;if (obj->back == obj->k)obj->back = 0;elseobj->back++;return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if (myCircularQueueIsEmpty(obj)){return false;}if (obj->front == obj->k)obj->front = 0;elseobj->front++;return true;
}int myCircularQueueFront(MyCircularQueue* obj) {if (myCircularQueueIsEmpty(obj)){return -1;}return obj->data[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj) {if (myCircularQueueIsEmpty(obj)){return -1;}if (obj->back == 0)return obj->data[obj->k];elsereturn obj->data[obj->back - 1];
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj);obj = NULL;
}


在这里插入图片描述

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

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

相关文章

鸿蒙(HarmonyOS)应用开发——ArkTs学习准备

介绍 前面我们已经介绍了,如何安装HarmonyOS的IDE ,那么现在我们来介绍一下。HarmonyOS 开发的语言——ArkTs. ArkTS 是HarmonyOS的开发语言,他是typescript 的扩展,而typesrcipt是javascript的超集,如果你不太熟悉typescript语法…

qml Loader使用介绍

QML Loader 是 Qt Quick 框架中的一个元素,它允许你动态地加载和卸载 QML 组件。Loader 的作用主要体现在以下几个方面: 延迟加载:Loader 允许你在需要时才加载组件,而不是在应用程序启动时一次性加载所有组件。这样可以加快应用程序的启动时间,因为它只需要初始化用户当前…

MIT_线性代数笔记:列空间和零空间

目录 前言子空间综述列空间 Column space零空间(或化零空间)Nullspaceb 值的影响 Other values of b 前言 本节继续研究子空间,特别是矩阵的列空间(column space)和零空间(nullspace)。 子空间…

FreeRTOS的并行与并发思考

FreeRTOS的任务触发是由滴答时钟触发SysTick中断来触发调度器执行或阻塞或挂起和切换任务的。 首先是任务的并发能力,FreeRTOS的任务执行是基于全抢占调度机制,任务优先级按在就绪列表中由高到低排布,系统首先执行最高优先级任务,…

Django web开发(一) - 前端

文章目录 前端开发1.快速开发网站2.标签2.1 编码2.2 title2.3 标题2.4 div和span2.5 超链接2.6 图片小结标签的嵌套2.7 列表2.8 表格2.9 input系列2.10 下拉框2.11 多行文本用户注册案例: 用户注册GET 方式POST 方式表单数据提交优化 3.CSS样式3.1 快速上手3.2 CSS应用方式1. 在…

Docker run 命令

docker run :创建一个新的容器并运行一个命令 语法 docker run [OPTIONS] IMAGE [COMMAND] [ARG...]OPTIONS说明: -a stdin:指定标准输入输出内容类型,可选STDIN/STDOUT/STDERR三项; -d:后台运行容器&am…

SAP-部分字段变更

在SAP中部分字段是可以自行调整的,例如下图 这个字段是客户组1,已经被改成一级经理,现在来操作改回客户组1 首先选择字段点击F1-技术信息-数据元素(双击) . . 保存,返回,激活,返…

redis运维(十八)pipeline

一 pipeline 流水线 说明: 这里讲解的不是jenkins的pipeline流水线这里pipeline: 管道 redis为什么要提供pipeline功能 事务和pipeline ① pipeline的理念 强调:单纯的pipeline跟事务没有关系redis-cli --pipe --> 使用了pipeline机制说明&a…

排序算法总结

1 排序算法 1.1 快速排序 1.1.1 算法思想 先取一个随机数,然后和数组的最后一个数交换 进行partition过程,也就是比数组最后一个数小的放在数组左边,大的放在右边,相等的在数组中间,最后把数组的最后一个数也要放到中…

【LeetCode刷题-回溯】-- 46.全排列

46.全排列 方法:回溯法 一种通过探索所有可能的候选解来找出所有的解的算法,如果候选解被确认不是一个解,回溯法会通过在上一步进行一些变化抛弃该解,即回溯并且再次尝试 使用一个标记数组表示已经填过的数 class Solution {pu…

【前端】yarn介绍和使用

yarn介绍和使用 一、什么是yarn?二、安装yarn三、yarn用法四、yarn更多用法 一、什么是yarn? yarn是快速、可靠、安全的依赖管理。 yarn官网:https://yarn.nodejs.cn/ Yarn 是代码的包管理器。 它允许你与世界各地的其他开发者使用和共享&am…

如何设置实现本地JumpServer远程访问管理界面

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。JumpS…

C语言for循环结构经典练习

文章目录 一、for循环基本知识二、经典例题及解析1.水仙花数2.求规定范围内的完数3.求规定范围内质数4.计算阶乘之和5.计算55555555555555(类型)6.计算112123123412345(类型)7.判断用户输入正整数的位数8.判断某正整数是否为回文数9.九九乘法表10.统计用户输入的字符中&#xf…

PTA 公路村村通

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。 输入格式: 输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N)&…

JVM 之 javac、java、javap 命令详解

目录 一. 前言 二. javac 命令 三. java 命令 四. javap 命令 一. 前言 在日常工作中,我们新建 Java工程,写好代码后,编译和运行几乎都是通过 IDE(如idea、eclipse)工具完成。但作为 Java开发者还是要了解下 Java虚…

Modbus RTU协议及modbus库函数使用

一、与Modbus TCP的区别 在一般工业场景使用modbus RTU的场景还是更多一些,modbus RTU基于串行协议进行收发数据,包括RS232/485等工业总线协议。 与modbus TCP不同的是RTU没有报文头MBAP字段,但是在尾部增加了两个CRC检验字节(CRC…

Android之在RecyclerView列表中实现单选

一、实现效果 单选、可取消选中、列表数据可更新(选择状态清空,可重新选择) RecyclerView列表单选 二、实现步骤 仅展示部分核心代码,请主要参考适配器的定义 1、Item布局 selected_tip_list_item.xml文件 包含一个TextView和…

Spring Boot集成MyBatis实现多数据源访问的“秘密”

文章目录 为什么需要多数据源?Spring Boot集成MyBatis的基础配置使用多数据源小结 🎉Spring Boot集成MyBatis实现多数据源访问的“秘密” ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系列文章专栏&…

力扣:178. 分数排名(Python3)

题目: 表: Scores ---------------------- | Column Name | Type | ---------------------- | id | int | | score | decimal | ---------------------- 在 SQL 中,id 是该表的主键。 该表的每一行都包含了一场比赛的分数。Score …