leetcode 622. 设计循环链表

这道题讲了两种方法,第一个代码是用数组实现的,第二个是用链表实现的,希望对你们有帮助

(最好在VS自己测试一遍,再放到 leetcode上哦)

下面的是主函数(作参考),静下心来慢慢测试


 622. 设计循环链表

题目

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

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

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

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

题目链接

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文字 和 画图 分析

  1. 思考什么情况下,队列为空,队列为满

定义一个 指针head,用来存放头节点的地址,和一个指针tail,用来存放尾节点的地址(这个思路和队列的实现是一样的)

按照正常思路,大多数人会以为(队列长度为k):

当 head = tail 为空,而 tail 是第 k 个节点的时候为满,却忽略一点,这是个循环链表

以下这种情况就不成立:

通过图我们知道 head = tail 无法判断是空还是满

所以我们换一种思路:

存放 k 个元素,但是开辟(k + 1)个节点,故意留下一个节点不放元素

情况就是这样的:

我们发现:

当 head = tail 为空;

当 tail 的下一个节点 = head为满;

    2.  选用数组还是链表去做

这里两者思路我都讲(代码仅供参考,能通过,但是我个人觉得有些地方没有处理好,其实可以更完善,听思路即可)

  • 用数组(head 和 tail 就是元素下标)

a. 首先明确这本质是一个循环链表

b. 实现过程可能会遇到的问题:

问题1:

这里可以看到 tail 不可能一直加加

如果是正确的思路,此时的图应该是这样:

所以我们这里要对 tail 进行处理:

这里可以通用

tail = tail % (k + 1)(head也会出现这样的情况,同样要这么处理)

问题2:

判断为满时,我们可能会犯错误

这种情况我们非常容易知道:判断

tail + 1 == head

但是这种情况就不适用了:

所以我们要写一个通式:

(tail + 1 ) % (k + 1) == head

问题3:

找到尾元素

正常情况下的尾元素很好找

尾元素的下标就是 tail - 1

如果是这样,就不好判断了

这里我们可以用 if ,else语句做区分,

也可以写一个通式:

(tail - 1 + k + 1) % (k + 1)

即:(tail + k )%(k + 1)

  • 用链表(head 和 tail 就是头节点和 尾节点的地址)

a. 这里可以写一个循环链表

可以在初始化的时候先搭建好这个循环链表,后面再存放元素

b. 只有一个地方需要注意:

就是找尾元素(实际上,应该是tail的上一个节点)

这里选择可以记录上一个节点的地址

或者 循环找到上一个节点


代码

代码1:

typedef int SLType;
typedef struct StackList
{
    SLType* a;
    int top;
    int rear;
    int k;
}SL;//创建数组
void SLInit(SL* head, int k)
{
    assert(head);
    head->a = (SLType*)malloc((k + 1) * sizeof(SLType));
    head->top = 0;
    head->rear = 0;
    head->k = k;
}//初始化数组
void SLPush(SL* head, SLType x)
{
    assert(head);
    head->a[head->rear] = x;
    head->rear++;
}//存放元素
void SLPop(SL* head)
{
    assert(head);
    head->top++;
}//删除元素


//以上都是数组的实现

typedef struct
{
    SL q;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k)
{
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    SLInit(&obj->q, k);
    return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
    SL* q1 = &obj->q;
    return  q1->rear == q1->top;
}//判断是否为空

bool myCircularQueueIsFull(MyCircularQueue* obj)
{
    SL* q1 = &obj->q;
    int a = q1->rear;
    a = (q1->rear + 1) % (q1->k + 1);
    return a  == q1->top;
}//判断是否为满

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
    if (myCircularQueueIsFull(obj))
    {
        return false;
    }
    else
    {
        SLPush(&obj->q, value);
        SL* q1 = &obj->q;
         q1->rear = q1->rear % (q1->k + 1);
        return true;
    }

}//存放元素

bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    else
    {
        SLPop(&obj->q);
        SL* q1 = &obj->q;
         q1->top = q1->top % (q1->k + 1);
        return true;
    }

}//删除元素

int myCircularQueueFront(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        return (&obj->q)->a[(&obj->q)->top];
    }
}//返回头元素

int myCircularQueueRear(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        if ((&obj->q)->rear == 0)
         {
            return (&obj->q)->a[(&obj->q)->k];
         } 
        return(&obj->q)->a[(&obj->q)->rear - 1];
    }
}//返回尾元素


void myCircularQueueFree(MyCircularQueue* obj)
{
    free(obj);
}//销毁空间

 代码2:

typedef int QLType;
typedef struct QueueNode
{
    QLType val;
    struct QueueNode* next;
}QN;//创建节点
typedef struct StackList
{
    QN* head;
    QN* tail;

}QL;//创建队列
void  QNInit(QL* pphead, int k)
{
    pphead->head = pphead->tail = NULL;
    QN* prev = NULL;
    k = k + 1;
    while (k--)
    {
        QN* newnode = (QN*)malloc(sizeof(QN));
        if (pphead->head == NULL)
        {
           prev =  pphead->head = pphead->tail = newnode;
        }
        else
        {
            pphead->tail = newnode;
            pphead->head->next = pphead->tail;
            pphead->tail->next = prev;
            pphead->head = pphead->tail;
        }
    }
    pphead->head =pphead->tail = prev;
}//初始化并链接节点

QLType QLTop(QL* pphead)
{
    return pphead->head->val;
}//返回首元素
QLType QLtail(QL* pphead)
{
    QN* rear = pphead->head;
    while (rear->next != pphead->tail)
    {
        rear = rear->next;
    }
    return rear->val;
}//返回尾元素
void QLpush(QL* pphead, int val)
{
    pphead->tail->val = val;
    pphead->tail = pphead->tail->next;
}//存放元素
void QLPop(QL* pphead)
{
    pphead->head = pphead->head->next;
}//删除元素


//以上是链表的创建


typedef struct
{
    QL q;
} MyCircularQueue;

MyCircularQueue * myCircularQueueCreate(int k)
{
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    QNInit(&obj->q, k);
    return obj;
}//初始化
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
    QL* q1 = &obj->q;
    return  q1->head == q1->tail;
}//判断是否为空

bool myCircularQueueIsFull(MyCircularQueue* obj)
{
    QL* q1 = &obj->q;
    return q1->tail->next == q1->head;
}//判断是否为满
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
    if (myCircularQueueIsFull(obj))
    {
        return false;
    }
    else
    {
        QLpush(&obj->q, value);
        return true;
    }

}//存放元素

bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    else
    {
        QLPop(&obj->q);
        return true;
    }
}//删除元素

int myCircularQueueFront(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        return QLTop(&obj->q);
    }
}//返回首元素

int myCircularQueueRear(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        return  QLtail(&obj->q);
    }
}//返回尾元素


void myCircularQueueFree(MyCircularQueue* obj)
{
    free(obj);
}//释放空间

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第二十一章——网络通信

一.网络程序设计基础 1.局域网与互联网 2.网络协议 1.IP协议 IP是Internet Protocol的简称,是一种网络协议。 1.1 TCP/IP层次结构 2.TCP与UDP协议 TCP可保证数据从一端送至另一端时,能够确实送达,而且抵达的数据的排列顺序和送出时的顺序相…

AWR1642 boost开发板支持的TI参考设计

打开radar_toolbox_1_30_00_05\source\ti\examples\examples_overview,通过输入“1642”查找AWR1642 BOOST支持的参考设计,通过筛选,支持AWR1642 BOOST的参考设计如下: 挑选出两个参考设计上手,一个是“nonos_oob_16xx",不带OS;另一个是”short range radar“,比较…

吹响AI技术应用的号角

毫无疑问,各企业正围绕各种技术展开一场持续不断的角逐,力争率先取得领先且具创新性的技术进步,AI技术也不例外。疫情期间,全球各地企业的员工纷纷转向居家办公。因此,为轻松实现这一转型并建立起远程办公的新常态&…

用23种设计模式打造一个cocos creator的游戏框架----(四)装饰器模式

1、模式标准 模式名称:装饰器模式 模式分类:结构型 模式意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更为灵活。 结构图: 适用于: 当需要给一个对象在运行时添加更…

使用命令行创建vue3项目等待时间长解决方案

问题描述 今天在使用命令行创建vue3项目的时候,发现命令行窗口卡了很久,明明已经更换了安装包的源,并且检查环境变量配置正确的情况下,为什么还要等待那么久呢? 解决方案 使用命令再次检查更换淘宝的源是否配置成功…

混沌映射初始化种群与随机初始化种群初始种群分布图对比

自行切换混沌映射,代码如下: Lb -1; % 搜索空间下界 Ub 1; % 搜索空间上界N_iter 500; % 最大迭代次数 N 30; % 种群个数 dim 2; % 种群维度 Z zeros(N, dim);% 随机生成一个d维向量 Z(1, :) rand(1, dim);% 利用logistic生成N个向量 for i…

C++新经典模板与泛型编程:用成员函数重载实现std::is_convertible

用成员函数重载实现is_convertible C标准库中提供的可变参类模板std::is_convertible,这个类模板的主要能力是判断能否从某个类型隐式地转换到另一个类型,返回的是一个布尔值true或false。例如,一般的从int转换成float或从float转换成int&am…

锁表的原因及解决办法

引言 作为开发人员,我们经常会和数据库打交道。 当我们对数据库进行修改操作的时候,例如添加字段,更新记录等,没有正确评估该表在这一时刻的使用频率,直接进行修改,致使修改操作长时间无法响应&#xff0…

孩子都能学会的FPGA:第二十四课——用FPGA和格雷码实现异步FIFO

(原创声明:该文是作者的原创,面向对象是FPGA入门者,后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门,作者不光让大家知其然,还要让大家知其所以然!每个工程作者都搭建了全自动化的仿…

数据结构 图的广度优先搜索和深度优先搜索

一、广度优先搜索 广度优先搜索等价于树的层次遍历,将起点的每一层进行遍历 当这一层结点全部被遍历完时,再遍历下一层次,从图中可以根据距离遍历起点的长度进行层次选择 例: 以a结点作为开始结点 a的下一层次有b c e三个结点 所以…

GIT GUI使用

文章目录 一、新建本地仓库二、推送(push) 一、新建本地仓库 在空白处右键,找到GIT GUI here, 如果没有仓库,出现的是这样的: 如果有仓库,在本地仓库里打开就是这样的: 新建本地…

Http协议与Tomcat

HTTP协议 HTTP协议(HyperText Transfer Protocol)即超文本传输协议 ,是TCP/IC网络体系结构应用层的一个客户端-服务端协议,是所有客户端,服务端数据传输的基石(数据传输规则) 特点 ⭐基于TCP协…

C++刷题 -- 链表

C刷题 – 链表 文章目录 C刷题 -- 链表1.删除链表的倒数第 N 个结点2.链表相交3.环形链表 1.删除链表的倒数第 N 个结点 https://leetcode.cn/problems/remove-nth-node-from-end-of-list/ 快慢指针的应用 fast指针先移动N步,slow依然指向head;然后fa…

算法-01-递归

1-理解递归 斐波那契数列(Fibonacci sequence),又称黄金分割数列 ,以兔子繁殖为例子而引入,故又称“兔子数列”,其数值为:1、1、2、3、5、8、13、21、34……特点是 从第三个数开始,第…

C语言指针详解上

1 野指针 int main01(){//野指针就是没有初始化的指针,指针的指向是随机的,不可以 操作野指针//int a 0;//指针p保存的地址一定是定义过的(向系统申请过的)int *p;//野指针*p 200;printf("%d\n",*p);system("pause");return 0;}2 空指针 空指针的作用…

【Spring 源码】 贯穿 Bean 生命周期的核心类之 AbstractAutowireCapableBeanFactory

🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…

C++【智能指针】

欢迎来到Cefler的博客😁 🕌博客主页:那个传说中的man的主页 🏠个人专栏:题目解析 🌎推荐文章:题目大解析(3) 目录 👉🏻为什么需要智能指针&#x…

java学习part40collections工具类

162-集合框架-Collections工具类的使用_哔哩哔哩_bilibili 1.collections工具类 感觉类似c的algorithm包,提供了很多集合的操作方法 2.排序 3.查找 4.复制替换 5.添加,同步

异常检测 | 基于孤立森林(Isolation Forest)的数据异常数据检测(结合t-SNE降维可视化)

异常检测 | MATLAB实现基于孤立森林的数据异常检测 目录 异常检测 | MATLAB实现基于孤立森林的数据异常检测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现基于孤立森林(Isolation Forest)的数据异常数据检测可视化(完整源码和数据) 基于孤立森林(…

如何将微服务注册到nacos服务上

首先可在maven的父工程的pom文件中添加maven的dependencyManagement标签&#xff0c;引入spring-cloud-alibaba-dependencies坐标 <properties><spring.cloud.alibaba.version>2.2.9.RELEASE</spring.cloud.alibaba.version></properties><!-- 管理…