LeetCode——622设计循环队列

news2025/2/27 9:20:22

. - 力扣(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.coloradmin.cn/o/1585307.html

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

相关文章

前端开发攻略---Vue通过自定义指令实现元素平滑上升的动画效果(可以自定义动画时间、动画效果、动画速度等等)。

1、演示 2、介绍 这个指令不是原生自带的,需要手动去书写,但是这辈子只需要编写这一次就好了,后边可以反复利用。 3、关键API IntersectionObserver IntersectionObserver 是一个用于监测元素是否进入或离开视口(viewport&#x…

Python零基础从小白打怪升级中~~~~~~~文件和文件夹的操作 (1)

第七节:文件和文件夹的操作 一、IO流(Stream) 通过“流”的形式允许计算机程序使用相同的方式来访问不同的输入/输出源。stream是从起源(source)到接收的(sink)的有序数据。我们这里把输入/输…

邮件群发提高成功率的技巧?如何群发邮件?

邮件群发有哪些注意事项?怎么有效分析邮件群发效果? 邮件群发已经成为一种高效的信息传递手段。然而,很多人发现,尽管发送了大量的邮件,但回应率却并不理想。那么,如何才能在邮件群发中提高成功率呢&#…

SWM341系列应用(LVGL应用)

SWM341系列之LVGL应用 1、LVGL 缓冲区的应用 现象:客户使用SWM34SRE时 ,客户不使用LVGL的前提下需要手动切换缓冲区,但是切换的时候显示不正常; 分析与解决:需要客户手动切换的时候VBPRELOAD寄…

el-tree基础渲染

el-tree 每个节点左右布局鼠标经过接电视&#xff0c;左边文字变色&#xff0c;右边不变 <el-tree:data"list":props"defaultProps"default-expand-all:expand-on-click-node"false"><template #default"{ data }"><e…

无线网络2.4和5G的区别

无线网络2.4和5的区别 无线网络2.4GHz和5GHz的主要区别在于频率、覆盖范围、传输速度、干扰能力和穿透性。以下是详细介绍&#xff1a;12 频率不同。2.4GHz的频率较低&#xff0c;而5GHz的频率较高。频率越低&#xff0c;信号在传播过程中的损失越小&#xff0c;因此覆盖范围…

【科研】搜索文献的网站

文章目录 paperswithcode【最新论文&#xff0c;代码】huggingface【大语言模型&#xff0c;最新论文】dblp【关键词搜索】arxiv【最新文章】semanticscholar【相关引用查询】connectedpapers【相关引用查询】github【工程&#xff0c;代码&#xff0c;论文开源代码】 paperswi…

[蓝桥杯 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越大…

高性能计算与深度学习结合;提升云人工智能基础设施可靠性;基于心理测量学的通用型人工智能评估;模仿人脑思维模式的视觉语言规划框架

编者按&#xff1a;欢迎阅读“科研上新”栏目&#xff01;“科研上新”汇聚了微软亚洲研究院最新的创新成果与科研动态。在这里&#xff0c;你可以快速浏览研究院的亮点资讯&#xff0c;保持对前沿领域的敏锐嗅觉&#xff0c;同时也能找到先进实用的开源工具。 本期内容速览 …

福克斯有什么明显的优缺点吗?

福克斯有什么明显的优缺点吗&#xff1f; - 知乎 https://www.zhihu.com/question/22125956/answer/554288301 作者&#xff1a;赵小瑚 链接&#xff1a;https://www.zhihu.com/question/22125956/answer/554288301 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作…

【Unity】组件组合使用心得(单行可自动拓展Scroll View)

在这之前&#xff0c;一直是在使用Scroll View进行滑动内容设置&#xff0c;但设置的都是不明不白的&#xff0c;而且有的时候设置好了之后也不知道是为什么&#xff0c;总感觉哪里不对劲&#xff0c;而且好也不知道为什么好&#xff0c;可能是长时间在做管理上的内容&#xff…

企业鸿蒙原生应用元服务备案实操基本材料要求

一、要提前准备的主要材料包括 域名&#xff0c;服务器&#xff0c;包名&#xff0c;公钥&#xff0c;MD5值&#xff0c;法人身份证正反两面&#xff0c;邮箱&#xff0c;手机号2个。 域名是备案过的&#xff0c;应为要求域名能打开&#xff0c;还要悬挂备案号。 操作时要提前沟…

java包目录命名

包目录命名 config controller exception model common entity enums reponse request repository security service util

看不懂来打我,vue3如何将template编译成render函数

前言 在之前的 通过debug搞清楚.vue文件怎么变成.js文件 文章中我们讲过了vue文件是如何编译成js文件&#xff0c;通过那篇文章我们知道了&#xff0c;template编译为render函数底层就是调用了vue/compiler-sfc包暴露出来的compileTemplate函数。由于文章篇幅有限&#xff0c;…

数据降维方法-主成分分析(PCA)

目录 一、前言 二、向量的表示及基变换 三、基变换 四、协方差矩阵 五、协方差 六、优化目标 一、前言 主成分分析(Principal Component Analysis) 用途&#xff1a;降维中的常用手段 目标&#xff1a;提取最有价值的信息&#xff08;基于方差&#xff09; 问题&#x…

使用 Citavi 和 NVivo 简化您的文献综述和研究分析

NVivo 是一款支持定性研究方法和混合研究方法的软件。它可以帮助您收集、整理和分析访谈、焦点小组讨论、问卷调查、音频等内容。NVivo&#xff08;1.0版&#xff09;是Windows和Mac的主要版本。遵循最新的主要版本NVivo 12&#xff08;Windows和Mac&#xff09;。 NVivo 强大…

前端开发攻略---利用Flexbox和Margin实现智能布局:如何巧妙分配剩余空间,让你的网页设计更上一层楼?

1、演示 2、flex布局 Flex布局是一种用于Web开发的弹性盒子布局模型&#xff0c;它可以让容器内的子元素在空间分配、对齐和排列方面具有更大的灵活性。以下是Flex布局的基本用法&#xff1a; 容器属性&#xff1a; display: flex;&#xff1a;将容器指定为Flex布局。flex-dire…

面试(02)————Java基础和集合

一、Java基础知识 1、面向对象的特征 2、Java 的基本数据类型有哪些 3、JDK JRE JVM 的区别 4、重载和重写的区别 5、Java中和equals的区别 6 、String、StringBuffer、StringBuilder三者之间的区别 7、接口和抽象类的区别是什么&#xff1f; 8、反射 9、jdk1.8 的新特…

行云堡垒国密算法应用与信创支持

一、 国密算法和信创的介绍 1.1 什么是国密算法 国密算法是国家密码管理局制定颁布的一系列的密码标准&#xff0c;即已经被国家密码局认定的国产密码算法&#xff0c;又称商用密码&#xff08;是指能够实现商用密码算法的加密&#xff0c;解密和认证等功能的技术&#xff09;…

视频图像的两种表示方式YUV与RGB(4)

本篇主要讲YUV与RGB之间的转换&#xff0c;包括YUV444 颜色编码格式 转为 RGB 格式 &#xff0c;RGB颜色编码格式转为 YUV444 格式。 一、 YUV与RGB之间的转换 YUV与RGB颜色格式之间进行转换时 , 涉及一系列的数学运算 ; YUV 颜色编码格式转为RGB格式的转换公式 取决于 于 YUV …