LeetCode662.设计循环队列||4种方法实现

news2024/9/22 21:15:51

目录

题目

 思路1(链表)

代码

思路2(数组)

 代码


题目

题目要求的队列需要实现的功能有
①Creat---设置队列长度
②Front---获取队列头
③Rear---获取队列尾
④en----插入元素
⑤de---删除元素
⑥empty---判空
⑦full---判满

 思路1(链表)

🔍普通队列长度没有限制,循环队列的长度是初始化时被规定的。

❓ 请思考:普通的队列我们可以通过链表来实现,那么环状的队列能否继续通过链表实现呢?
💡答案:可以,需要将链表设计为循环链表。🔑解析:这样可以通过最后一个链表节点找到第一个链表节点。

❓请思考:怎么通过循环链表构造循环队列呢?
构造出一个循环链表,定义front指向队列头,定义back指向队列尾后一个空间。规定front==back时队列为空。

 🔨插入4个元素

 ❗注意:此时不能继续插入元素了,如果在插入元素,back接下来就和front一样,而这是我们之前定义队列为空的条件。也就是说:在前提条件front==back表示队列为空时,循环链表有5个节点,只能存储4个数据,推而广之,如果想要队列中存放k个数据,那么循环链表需要定义(k+1)个节点。

🔨删除元素:删除队列头只需要将链表头删即可。

 ❗注意:🚫头删不要将需要删除数据所在的空间释放,这样可能会导致下次插入元素时非法访问内存空间。头删只需要让front指向下一个空间即可。front和back之间的数据才是队列中的元素。

❓请思考:怎么找到队列尾?
💡解决方案:
①循环队列结构中添加一个preTail指针,指向链表尾节点的前一个结点。
②遍历整个链表,在链表尾节点的前一个节点时停止遍历。
③使用双向循环链表。

三种方案大同小异,这里不在赘述

代码

💬方案1代码

//使用链表实现循环队列
typedef struct Qnode
{
    struct Qnode* next;
    int val;
}Qnode;
typedef struct MyCircularQueue{
    Qnode* head;
    Qnode* tail;
    Qnode* preTail;
    int size;
    int capacity;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    q->size = 0;
    q->capacity = k;
    //创建第一个空间
    q->head = (Qnode*)malloc(sizeof(Qnode));
    q->tail = q->head;
    q->preTail = NULL;
    Qnode* cur = q->head;
    //创建k个节点
    while (k--)
    {
        cur->next = (Qnode*)malloc(sizeof(Qnode));
        cur = cur->next;
    }
    cur->next = q->head;
    return q;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //队列满了插入失败
    if (obj->tail->next == obj->head)
        return false;
   //插入数据
   obj->tail->val = value;
   obj->preTail = obj->tail;
   obj->tail = obj->tail->next;
   obj->size++;
   return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    //队列为空删除失败
    if (obj->size == 0)
        return false;
    //链表头删(不要销free节点的空间)
    obj->head = obj->head->next;
    obj->size--;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    return obj->size == 0 ? -1 : obj->head->val;
}

int myCircularQueueRear(MyCircularQueue* obj) {
    return obj->size == 0 ? -1 : obj->preTail->val;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->size == 0;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return obj->size == obj->capacity;
}

void myCircularQueueFree(MyCircularQueue* obj) {
    //需要释放k+1个节点
    int cnt = obj->capacity + 1;
    Qnode* cur = obj->head;
    while (cnt--)
    {
        Qnode* tmp = cur->next;
        free(cur);
        cur = tmp;
    }
    free(obj);
}

💬方案2代码

//使用链表实现循环队列
typedef struct Qnode
{
    struct Qnode* next;
    int val;
}Qnode;
typedef struct MyCircularQueue{
    Qnode* head;
    Qnode* tail;
    int size;
    int capacity;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    q->size = 0;
    q->capacity = k;
    //创建第一个空间
    q->head = (Qnode*)malloc(sizeof(Qnode));
    //tail==front,初始化为空
    q->tail = q->head;
    Qnode* cur = q->head;
    //创建k个节点
    while (k--)
    {
        cur->next = (Qnode*)malloc(sizeof(Qnode));
        cur = cur->next;
    }
    cur->next = q->head;
    return q;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //队列满了插入失败
    if (obj->size == obj->capacity)
        return false;
   //插入数据
   obj->tail->val = value;
   obj->tail = obj->tail->next;
   obj->size++;
   return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    //队列为空删除失败
    if (obj->size == 0)
        return false;
    //链表头删(不要销free节点的空间)
    obj->head = obj->head->next;
    obj->size--;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    return obj->size == 0 ? -1 : obj->head->val;
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if (obj->size == 0)
        return -1;
    //遍历链表
    Qnode* cur = obj->head;
    while (cur->next != obj->tail)
    {
        cur = cur->next;
    }
    return cur->val;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->size == 0;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return obj->size == obj->capacity;
}

void myCircularQueueFree(MyCircularQueue* obj) {
    //需要释放k+1个节点
    int cnt = obj->capacity + 1;

    Qnode* cur = obj->head;
    while (cnt--)
    {
        Qnode* tmp = cur->next;
        free(cur);
        cur = tmp;
    }
    free(obj);
}

💬方shu'zu案3代码

//使用链表实现循环队列
typedef struct Qnode
{
    struct Qnode* next;
    struct Qnode* pre;
    int val;
}Qnode;
typedef struct MyCircularQueue{
    Qnode* head;
    Qnode* tail;
    int size;
    int capacity;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    q->size = 0;
    q->capacity = k;
    //创建第一个空间
    q->head = (Qnode*)malloc(sizeof(Qnode));
    //tail==front,初始化为空
    q->tail = q->head;
    Qnode* cur = q->head;
    //创建k个节点
    while (k--)
    {
        Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
        cur->next = newnode;
        newnode->pre = cur;
        cur = cur->next;
    }
    cur->next = q->head;
    q->head->pre = cur;
    return q;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //队列满了插入失败
    if (obj->size == obj->capacity)
        return false;
   //插入数据
   obj->tail->val = value;
   obj->tail = obj->tail->next;
   obj->size++;
   return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    //队列为空删除失败
    if (obj->size == 0)
        return false;
    //链表头删(不要销free节点的空间)
    obj->head = obj->head->next;
    obj->size--;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    return obj->size == 0 ? -1 : obj->head->val;
}

int myCircularQueueRear(MyCircularQueue* obj) {
   return obj->size == 0 ? -1 : obj->tail->pre->val;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->size == 0;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return obj->size == obj->capacity;
}

void myCircularQueueFree(MyCircularQueue* obj) {
    //需要释放k+1个节点
    int cnt = obj->capacity + 1;

    Qnode* cur = obj->head;
    while (cnt--)
    {
        Qnode* tmp = cur->next;
        free(cur);
        cur = tmp;
    }
    free(obj);
}

思路2(数组)

❓先思考:通过数组实现的环形队列有哪些成员?
🔑数组、队列头下标、队列尾下标、队列元素个数、队列最大容量。

我们规定头下标和尾下标相等时队列为空。
📚来看数组模拟循环队列示意图(队列的容量是5):
①🔨队列为空

 ②🔨入队

 ③🔨出队

 

 ④🔨入队​​​​​​​

❗注意:从上述过程中可以观察到:在物理结构中 ,队尾可能在队头的前面也可能在队头后面。
🔺思维导图:

 代码

typedef struct {
    int* a;//a指向数组
    int front;//头下标
    int back;//尾下标
    int size;//队列元素个数
    int capacity;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    q->a = (int*)malloc(sizeof(int) * (k + 1));
    q->size = 0;
    q->capacity = k;
    q->front = q->back = 0;
    return q;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //队列已满
    if (obj->size == obj->capacity)
        return false;
    obj->a[obj->back] = value;
    obj->back++;
    //尾下标越界归0
    if (obj->back > obj->capacity)
    {
        obj->back = 0;
    }
    obj->size++;
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (obj->size == 0)
        return false;
    obj->front++;
    //头下标越界归0
    if (obj->front > obj->capacity)
        obj->front = 0;
    obj->size--;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    return obj->size == 0 ? -1 :  obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    //空队列
    if (obj->size == 0)
        return -1;
    if (obj->back == 0)
    {
       return obj->a[obj->capacity];
    }
    return obj->a[obj->back - 1];
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->size == 0;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return obj->size == obj->capacity;
}

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

 

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

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

相关文章

MySQL高级——第16章_多版本并发控制

第16章_多版本并发控制 1. 什么是MVCC MVCC (Multiversion Concurrency Control),多版本并发控制。顾名思义,MVCC 是通过数据行的多个版本管理来实现数据库的 并发控制 。这项技术使得在InnoDB的事务隔离级别下执行 一致性读 操…

ARM学习笔记_1 介绍,Keil环境搭建

从零开始学ARM 学习自b站一口linux老师的课程。 文章目录 从零开始学ARM介绍为什么要学汇编?ARM是什么?SOC计算机历史冯诺依曼结构介绍哈佛架构介绍混合架构介绍CPU运行原理 环境搭建 介绍 学习ARM需要学计算机原理,汇编,C语言&…

强大,Midjourney Imagine API接口,AI画画的福音!

前几天跟大家分享过一篇 ”让chatGPT教你AI绘画|如何将chatGPT与Midjourney结合使用?“,但是由于许多小伙伴们使用Midjourney还有许多困难,又要上网,还要注册Discord,MJ的使用成本很高,让大家望而却步&…

【计算机视觉 | 目标检测】目标检测中的评价指标 mAP 理解及计算(含示例)

文章目录 一、目标检测的评价指标1.1 Precision1.2 Recall1.3 Average Precision(AP)1.4 mean Average Precision(mAP)1.5 Intersection over Union(IoU)1.6 F1-score 二、基础知识2.1 Precision2.2 Recall…

5.20下周黄金行情走势分析及开盘独家交易策略

近期有哪些消息面影响黄金走势?下周黄金多空该如何研判? ​黄金消息面解析:周五(5月19日),现货黄金价格下跌又反弹,现货黄金持续走高美联储主席鲍威尔:那些积极的供应冲击不太可能重复出现,美联…

初阶数据结构之单链表的实现(四)

文章目录 链表的概念及结构一、链表的逻辑结构是什么样的?二、链表的初始化2.1链表初始化的示意2.2链表初始化代码实现 三、链表的各类接口函数定义四、链表的各类接口函数的代码实现4.1链表的打印代码实现4.1.1打印代码的实现 4.2链表的尾插代码实现4.2.1尾插代码实…

Mongodb 6.0 变化的配置参数与连接的方式变化

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共…

【故障排查】【伪处理】Jenkins在iframe窗口无法添加secret text凭证

问题描述 环境的ingress是,有个 svc 暴露 30080 -> 80 大致流程: svc(ingress-nginx) 30080端口 -> pod (nginx-ingress-controller ) 80端口 -> ingress -> svc -> pod (Jenkins 8080端口&#xff0…

基于粒子群优化算法的路径问题优化研究及其在Python中的实现

基于粒子群优化算法的路径问题优化研究及其在Python中的实现 文章目录 基于粒子群优化算法的路径问题优化研究及其在Python中的实现一、简介二、引言1、粒子群优化算法简介2、PSO算法与鸟群的类比 三、PSO算法数学原理1、粒子的位置和速度2、适应度函数3、粒子的个体最优和全局…

基于html+css的图展示80

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

从零开始搭建属于自己的hexo博客

前提要素:一个提供博客运行的服务器或者XX云。 先展示一下搭建好的样子,给大家一点动力: 整个搭建过程大概需要30分钟不到,请各位控制自己的时间~ 好了,废话不多说我们开始! 1、首先登录我们准备好的服…

redis高级篇二(分片集群)

一)进行测试Sentinel池: ​ Controller public class RestController {RequestMapping("/Java100")ResponseBodypublic String start(){//1.配置信息HashSet<String> setnew HashSet<>();// 连接信息 ip:port// set.add("127.0.0.1:27001");se…

[抓包] 微信小程序(PC版)如何抓包

本文抓包环境 Win10&#xff0c;微信(PC版本) v3.9.2.20&#xff0c;Burp Suite v1.7.32&#xff0c;Proxifier v3.42 不使用安卓模拟器 一、下载安装好Burp Suite&#xff0c;Proxifier 链接: https://pan.baidu.com/s/177BIEgCmZG9MfqQ4D0PTsg 提取码: 3hex 二、开始抓包 …

【ASP.NET Core笔记】 使用razor pages构建网站

使用ASP.NET Core Razor Pages 构建网站 sqlite 北风数据库 1. Northwind.Common.DataContext.Sqlite 是Sqlite的数据库上下文&#xff0c;有三个类&#xff1a;ConsoleLogger.csNorthwindContext.csNorthwindContextExtensions.cs 1.1 NorthwindContext 继承自 Microsoft.Enti…

计算机图形学-GAMES101-10

一、纹理 原模型网格->逐面Shading->逐像素Phong Shading->纹理贴图->换个纹理再贴图->环境光照。 &#xff08;1&#xff09;环境贴图 纹理就是一张图&#xff0c;纹理是GPU里的一块内存&#xff0c;可以进行点查询、范围查询、滤波。  环境光贴图、环境光映…

The authenticity of host ‘gitee.com (212.64.63.190)‘ can‘t be established.

在将本地仓库的代码推送到远程仓库时&#xff0c;出现下面报错。 $ git push -u origin master The authenticity of host gitee.com (212.64.63.190) cant be established. ECDSA key fingerprint is SHA256:FQGC9Kn/eye1W8icdBgrQpKkGYoFgbVr17bmjey0Wc. Are you sure you w…

Kali-linux分析密码

在实现密码破解之前&#xff0c;介绍一下如何分析密码。分析密码的目的是&#xff0c;通过从目标系统、组织中收集信息来获得一个较小的密码字典。本节将介绍使用Ettercap工具或MSFCONSOLE来分析密码。 8.2.1 Ettercap工具 Ettercap是Linux下一个强大的欺骗工具&#xff0c;也…

Mysql中常用到的查询关键字

文章目录 1、join2、like 模糊查询3、or4、distinct5、in 包含6、group by 分组7、order by8、limit 1、join MySQL 的连接主要分为内连接和外连接。 什么是内连接&#xff1a; 取得两张表中满足存在连接匹配关系的记录。 什么是外连接&#xff1a; 不只取得两张表中满足存在…

设计高端大气上档次的时尚品?!微软工程师借助AIGC成功圆梦!

&#xff08;本文阅读时间&#xff1a;5 分钟&#xff09; 在这个创意横飞、想象力爆棚的时代中&#xff0c;有很多美丽且吸引人的东西围绕在我们身边。然而&#xff0c;遗憾的是&#xff0c;被誉为“攻城狮”的我&#xff0c;内心里虽然非常喜欢且欣赏这些夺目的作品&#xff…

手动输入域账号自动禁用windows域用户的脚本

禁用windows域用户的脚本&#xff0c;需求&#xff1a; 1、显示该域用户的创建时间&#xff0c;最后登录时间和存放的OU&#xff0c; 2、将该账号禁用&#xff1b; 3、禁用后重新返回交互界面等待输入新的域账号。 Powershell脚本内如下&#xff1a; # 无限循环等待用户的输入…