LeetCode——622设计循环队列

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/design-circular-queue/

1.题目

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。

示例:

MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
circularQueue.enQueue(1);  // 返回 true
circularQueue.enQueue(2);  // 返回 true
circularQueue.enQueue(3);  // 返回 true
circularQueue.enQueue(4);  // 返回 false,队列已满
circularQueue.Rear();  // 返回 3
circularQueue.isFull();  // 返回 true
circularQueue.deQueue();  // 返回 true
circularQueue.enQueue(4);  // 返回 true
circularQueue.Rear();  // 返回 4

提示:

  • 所有的值都在 0 至 1000 的范围内;
  • 操作数将在 1 至 1000 的范围内;
  • 请不要使用内置的队列库。

2.解析

我们设计循环队列的关键是要有效地利用数组空间,并且能够处理队列满和队列空的情况。下面是一种使用数组实现循环队列的解法,其中back=k+1的含义是为了区分队列满和队列空的情况

  • 首先,我们需要定义一个固定大小的数组a来存储队列元素,以及两个指针front和back来标记队列的头部和尾部。

  • 初始化时,将front和back都设置为0,表示队列为空。

  • 判断队列是否为空(isEmpty):

    • 判断front是否等于back,如果相等,则表示队列为空,返回true;否则,返回false。
  • 判断队列是否已满(isFull):

    • 判断(back+1)%k是否等于front,如果相等,则表示队列已满,返回true;否则,返回false。
  • 入队操作(enqueue):

    • 首先,判断队列是否已满,即(back+1)%k是否等于front。如果相等,则表示队列已满,无法继续入队。
    • 如果队列未满,则将元素放入back指向的位置,并将back指针向后移动一位,即back=(back+1)%k。
  • 出队操作(dequeue):

    • 首先,判断队列是否为空,即front是否等于back。如果相等,则表示队列为空,无法进行出队操作。
    • 如果队列不为空,则将front指向的元素出队,并将front指针向后移动一位,即front=(front+1)%k。
  • 获取队头元素(getFront):

    • 首先,判断队列是否为空,即front是否等于back。如果相等,则表示队列为空,无法获取队头元素。
    • 如果队列不为空,则返回front指向的元素。

3.代码总结

1.构造器函数,用于创建一个指定长度的循环队列。

首先,通过malloc函数动态分配了一个MyCircularQueue结构体的内存空间,并将其地址赋给指针变量obj。

然后,通过malloc函数再次动态分配了一个整型数组的内存空间,并将其地址赋给指针变量obj->a。这个数组的长度为k+1,多分配了一个空间用于判断队列是否满的条件。

接着,将队列的头指针front和尾指针back都初始化为0。

最后,将k的值赋给队列的长度k。

最终,返回指向创建的循环队列的指针obj。

MyCircularQueue* myCircularQueueCreate(int k)//构造器,设置队列长度为 k {MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->a=(int*)malloc(sizeof(int)*(k+1));obj->front=0;obj->back=0;obj->k=k;return obj;
}

2. 检查循环队列是否为空

函数的返回值是一个bool类型的值,表示循环队列是否为空。

如果循环队列为空,则返回true,否则返回false。

函数的实现是通过比较循环队列的front和back的值来判断循环队列是否为空。

如果它们相等,说明队列中没有元素,即队列为空,返回true;否则返回false。

bool myCircularQueueIsEmpty(MyCircularQueue* obj)//检查循环队列是否为空。{return obj->front==obj->back;
}

3. 检查循环队列是否已满

函数的返回值是一个bool类型的值,表示循环队列是否已满。如果循环队列已满,则返回true,否则返回false。

函数的实现是通过计算(back+1)%(k+1)与front的值是否相等来判断循环队列是否已满。

如果它们相等,说明队列已满,返回true;否则返回false。

这里使用了取模运算来实现循环队列的特性。由于循环队列的尾部和头部相连,所以需要将back的下一个位置计算为(back+1)%(k+1),其中k为队列长度。如果这个值与front相等,说明队列已满。

bool myCircularQueueIsFull(MyCircularQueue* obj)//检查循环队列是否已满。{return (obj->back+1)%(obj->k+1)==obj->front;
}

4. 向循环队列插入一个元素

函数的返回值是一个bool类型的值,表示插入操作是否成功。

如果插入成功,则返回true;否则返回false。

函数的实现首先通过调用myCircularQueueIsFull函数来检查循环队列是否已满。

如果队列已满,则表示无法插入新元素,直接返回false。

如果队列未满,则将value值插入到队列的obj->back位置,并且将obj->back的值加1。为了保证obj->back在[0, k]的范围内,需要使用取模运算进行处理,即obj->back%=(obj->k+1)。这样可以使back的值在超出队列长度时重新回到队列起始位置。

最后返回true表示插入成功。

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)//向循环队列插入一个元素。如果成功插入则返回真。{if(myCircularQueueIsFull(obj)){return false;}obj->a[obj->back]=value;obj->back++;obj->back%=(obj->k+1);//将 obj->back 除以 (obj->k+1) 的余数,然后将结果赋值给 obj->back。return true;
}

5. 循环队列中删除一个元素

函数的返回值是一个bool类型的值,表示删除操作是否成功。

如果删除成功,则返回true;否则返回false。

函数的实现首先通过调用myCircularQueueIsEmpty函数来检查循环队列是否为空。

如果队列为空,则表示无法执行删除操作,直接返回false。

如果队列不为空,就执行删除操作。

即将obj->front的值加1,然后使用取模运算来确保obj->front在[0, k]的范围内。

最后返回true表示删除成功。

bool myCircularQueueDeQueue(MyCircularQueue* obj)//从循环队列中删除一个元素。如果成功删除则返回真。{if(myCircularQueueIsEmpty(obj)){return false;}obj->front++;obj->front%=(obj->k+1);return true;}

6.循环队列中获取队首元素

函数的返回值是一个int类型的值,表示队首元素。如果队列为空,则返回-1。

函数的实现首先通过调用myCircularQueueIsEmpty函数来检查循环队列是否为空。如果队列为空,则返回-1。

如果队列不为空,则直接返回obj->a[obj->front],即队首元素的值。

int myCircularQueueFront(MyCircularQueue* obj)//从队首获取元素。如果队列为空,返回 -1 。{if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[obj->front];
}

 7.获取循环队列的队尾元素

  1. 首先判断队列是否为空,通过调用函数myCircularQueueIsEmpty(obj)来判断。如果队列为空,则返回-1。
  2. 如果队列不为空,使用取模运算(obj->back+obj->k)%(obj->k+1)来计算队尾元素的下标。这里obj->back表示队尾元素的下标,obj->k表示队列的容量减1。这样做是为了实现循环队列的封装。
  3. 返回队尾元素obj->a[(obj->back+obj->k)%(obj->k+1)],即对应下标位置上的元素值。
int myCircularQueueRear(MyCircularQueue* obj)//: 获取队尾元素。如果队列为空,返回 -1 。{if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[(obj->back+obj->k)%(obj->k+1)];
}

8.释放循环队列的内存空间

首先,通过调用free(obj->a)来释放存储队列元素的数组的内存空间。obj->a指向数组的起始地址,free(obj->a)将释放该内存空间。

然后,通过调用free(obj)来释放存储循环队列结构体的内存空间。obj指向循环队列结构体的起始地址,free(obj)将释放该内存空间。

通过这两个free()函数的调用,可以确保循环队列所占用的所有内存空间都被释放,防止内存泄漏。

void myCircularQueueFree(MyCircularQueue* obj){free(obj->a);free(obj);
}

9.总的代码

typedef struct 
{int *a;int front;int back;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k)//构造器,设置队列长度为 k {MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->a=(int*)malloc(sizeof(int)*(k+1));obj->front=0;obj->back=0;obj->k=k;return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)//检查循环队列是否为空。{return obj->front==obj->back;
}bool myCircularQueueIsFull(MyCircularQueue* obj)//检查循环队列是否已满。{return (obj->back+1)%(obj->k+1)==obj->front;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)//向循环队列插入一个元素。如果成功插入则返回真。{if(myCircularQueueIsFull(obj)){return false;}obj->a[obj->back]=value;obj->back++;obj->back%=(obj->k+1);//将 obj->back 除以 (obj->k+1) 的余数,然后将结果赋值给 obj->back。return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj)//从循环队列中删除一个元素。如果成功删除则返回真。{if(myCircularQueueIsEmpty(obj)){return false;}obj->front++;obj->front%=(obj->k+1);return true;}int myCircularQueueFront(MyCircularQueue* obj)//从队首获取元素。如果队列为空,返回 -1 。{if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj)//: 获取队尾元素。如果队列为空,返回 -1 。{if(myCircularQueueIsEmpty(obj)){return -1;}return obj->a[(obj->back+obj->k)%(obj->k+1)];
}void myCircularQueueFree(MyCircularQueue* obj){free(obj->a);free(obj);
}

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

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

相关文章

银行渠道整合平台应用架构

渠道整合平台将 功能微服务化,将服务流程标准化。微服务 化的功能能够进行各种组合使用。而标准化的流程可同时作用于所有渠道,保证体验一致。未来在进行流程变更的时候可有效避免各渠道的重复开发。 • 渠道整合平台避免了各个渠道对于同一个业务的差异…

【HTML】简单制作一个动态3D正方体

目录 前言 开始 HTML部分 JS部分 CSS部分 效果图 总结 前言 无需多言,本文将详细介绍一段代码,具体内容如下: 开始 首先新建文件夹,创建两个文本文档,其中HTML的文件名改为[index.html],JS的文件名改…

FreeRTOS学习 -- 移植

一、添加FreeRTOS源码 在基础工程中新建一个名为FreeRTOS的文件夹,创建FreeRTOS文件夹以后将FreeRTOS的源码添加到这个文件夹中。 portable 文件夹,只需要保留keil、MemMang 和 RVDS这三个文件夹,其他的都可以删除掉。 移植FreeRTOSConfig…

vue3新手笔记

setup(){}函数,是启动页面后,自动执行的一个函数。所有数据(常量、变量)、函数等等,都要return 出去。 ref函数(可用于基本数据类型,也可以用于复杂数据类型):让页面上的…

Swagger转换成Excel文件

1、添加swagger解析依赖包&#xff1a; <dependency><groupId>io.swagger.parser.v3</groupId><artifactId>swagger-parser</artifactId><version>2.1.12</version></dependency>2、示例代码&#xff1a; package com.rlclou…

TCP/IP 协议栈在 Linux 内核中的 运行时序分析

1、Linux内核概述 1.1 Linux内核结构 一个完整的Linux内核一般由5部分组成&#xff0c;它们分别是内存管理、进程管理、进程间通信、bai虚拟文件系统和网络接口。 1、内存管理 内存管理主要完成的是如何合理有效地管理整个系统的物理内存&#xff0c;同时快速响应内核各个子…

[蓝桥杯 2018 国 C] 迷宫与陷阱

题目&#xff1a; 思路&#xff1a; 代码&#xff1a; #include <bits/stdc.h> using namespace std; const int N1e310; char g[N][N];//输入&#xff1a;图的数组 int vis[N][N]; /* 剪枝&#xff1a;记录magic的个数&#xff08;一个点经过两次&#xff0c;magic越大…

创建真实项目vue2项目

1. 创建 vue create 项目名 2. 选择自定义 3. 勾选以下必备选项 4.选择使用vue2 5. 选择哈希模式&#xff08;n&#xff09;; css选择Less 6. ESLint校验 选择 7. 保存&#xff08;按照默认&#xff09; 8. 在哪里添加ESLint文件 9. 要不要把这个改成将来的预设&am…

4.Spring IoCDI

文章目录 1.Ioc - 控制反转(解耦)1.1传统开发1.2批量生产车轮(修改代码) - 传统方式&#xff0c;繁琐1.3解耦1.3.1使用Ioc方法后1.3.2添加变量颜色 只需要修改Tire即可 1.4Bean的存储1.4.1Controller(控制器存储)1.4.2Service(服务存储)1.4.2.1根据context来获取bean1.4.2.2根据…

SSM整合----第一个SSM项目

文章目录 前言一、使用步骤1.引入库2.建表3 项目结构4 web.xml的配置5 配置数据源6 SpringMVC配置7 配置MyBatis Mapper8 书写控制类 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; SSM整合是指Spring、SpringMVC和MyBatis这三个框架的整合使用。…

【汇编语言实战】对输入的数组实现快速排序

C语言描述&#xff1a; #include <stdio.h>// 交换数组中两个元素的位置 void swap(int *a, int *b) {int temp *a;*a *b;*b temp; }// 分区函数&#xff0c;将数组按照基准值划分为两部分 int partition(int arr[], int low, int high) {int pivot arr[high]; // 选…

JavaWeb中的Servlet是什么?怎么使用?

文章目录 一、什么是Servlet二、Servlet的基本内容1、Servlet的作用2、Servlet接口3、Servlet接口实现类4、Servlet接口实现类开发步骤5、Servlet对象生命周期6、HttpServletResquest接口7、HttpServletResponse接口8、请求对象和响应对象流程图9、请求对象和响应对象生命周期1…

阿里面试总结 一

写了这些还是不够完整&#xff0c;阿里 字节 卷进去加班&#xff01;奥利给 ThreadLocal 线程变量存放在当前线程变量中&#xff0c;线程上下文中&#xff0c;set将变量添加到threadLocals变量中 Thread类中定义了两个ThreadLocalMap类型变量threadLocals、inheritableThrea…

迷宫 — — 蓝桥杯(动态规划)

迷宫 题目&#xff1a; 输入样例&#xff1a; 3 1 1 1 2 3 4 5 6 7 8 9 2 2 1 3 1 R输出样例&#xff1a; 21思路&#xff1a; 题目大意&#xff1a;给定一个n x m的平面网格&#xff0c;并且每一个格子都有一定的代价&#xff0c;并且设有障碍物和陷阱&#xff0c;障碍物的意…

c++的友元函数,详细笔记,细说三种友元用法

解释友元 友元用通俗易懂的话来说&#xff0c;就是&#xff1a;当有人来到你家里&#xff0c;他就只能呆在客厅里面&#xff0c;你是不可能让他来到你的卧室之中的。但是如果这个人是你的朋友&#xff0c;那么你是默许他可以进入你的卧室的。 此时呢&#xff1f;我告诉你&…

网络IO模型以及实际应用

网络IO模型 本文主要介绍了几种不同的网络IO模型&#xff0c;以及实际应用中使用到的Reactor模型等。 我们常说的网络IO模型&#xff0c;主要包含阻塞IO、非阻塞IO、多路复用IO、信号驱动IO、异步IO。 根据第一个阶段&#xff1a;是否需要阻塞&#xff0c;分为阻塞和非阻塞IO。…

【从浅学到熟知Linux】进程状态与进程优先级(含进程R/S/T/t/D/X/Z状态介绍、僵尸进程、孤儿进程、使用top及renice调整进程优先级)

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程及数据库等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 进程状态进程状态查看R运行状态&#xff08;running&#xff09;S睡眠状态&#xff08;sleeping&a…

GT收发器64B66B协议(2)自定义PHY设计

文章目录 前言一、设计框图二、GT_module三、PHY_module3.1、PHY_tx模块3.2、PHY_rx_bitsync模块3.3、PHY_rx模块 四、上板测试总结 前言 有了对64B66B协议的认识以及我们之前设计8B10B自定义PHY的经验&#xff0c;本文开始对64B66B自定义PHY的设计 一、设计框图 二、GT_modu…

Harmony鸿蒙南向驱动开发-UART

UART指异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter&#xff09;&#xff0c;是通用串行数据总线&#xff0c;用于异步通信。该总线双向通信&#xff0c;可以实现全双工传输。 两个UART设备的连接示意图如下&#xff0c;UART与其他模块一般用2线&a…

数据结构初阶:栈和队列

栈 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。 栈中的数据元素遵守后进先出 LIFO &#xff08; Last In First Out &#xff09;的原则。…