【数据结构】如何设计循环队列?图文解析(LeetCode)

这篇具有很好参考价值的文章主要介绍了【数据结构】如何设计循环队列?图文解析(LeetCode)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

LeetCode链接:622. 设计循环队列 - 力扣(LeetCode)

目录

做题思路

只开辟 k 个空间

多开一个空间

代码实现

1. 循环队列的结构

2. 开辟空间

3. 判断空

4. 判断满

5. 队尾插入数据

6. 队头删除数据

7. 获取队头元素

8. 获取队尾元素

9. 销毁队列

全部代码


做题思路

  • 设计循环队列,使用数组或链表都可以,各有优劣
  • 本文使用数组实现
  • 本文使用C语言实现

假设队列长度 k = 4

多开一块空间(开辟 k+1 块空间)可以方便区分空和满

为什么?

举个栗子:

只开辟 k 个空间

如果只开辟 k 个空间(假设 k = 4):

  • front(队头)
  • rear(队尾)
  • front 和 rear 初始都为 0

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

如果插入一个数据呢?

front 不变,rear 向后移动,如下图:

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

理想的判断空条件:

  • 队头 == 队尾,队列为空
  • 队头 != 队尾,队列非空

目前看来似乎可以正常判断队列是否为空

那如果队列满了呢?

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

如上图所示,队列满了

rear 又回到了 front 的位置

现在怎么判断满呢?

rear == front 吗?

似乎和前面判断空冲突了

想判断必须要特殊处理:比如加一个变量 size 来记录队列中元素的个数

这种方法虽然可以,但是会让代码显得很臃肿,于是我选择了另一种方法:

多开一个空间

如果多开了一个空间(开辟 k+1 个空间):

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

  • 这里多开的空间是不存放数据的
  • 这块空间存在的意义就是为了方便区分空和满

下面我将演示一下如何判断:

判断空:

  • 队头 == 队尾,队列为空
  • 队头 != 队尾,队列非空

判断满:

  • 队尾的下一个 == 队头,队列已满
  • 队尾的下一个 != 队头,队列未满

如下图:

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

那么好,这里简单介绍了一下我的实现思路:

  • 使用C语言实现
  • 使用数组实现
  • 数组多开一块空间

接下来就是详细的实现方法


代码实现

本题要求:

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

1. 循环队列的结构

//循环队列的结构
typedef struct
{
    int* a;     //一个数组
    int front;  //存放队头的下标
    int rear;   //存放队尾的下标
    int k;      //队列长度
} MyCircularQueue;

2. 开辟空间

//开辟空间并初始化
MyCircularQueue* myCircularQueueCreate(int k)
{
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    //多开一个方便区分空和满
    obj->a = (int*)malloc(sizeof(int) * (k + 1));
    obj->front = obj->rear = 0;
    obj->k = k;
    return obj;
}

3. 判断空

前面说过了,队头等于队尾时,队列为空

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

4. 判断满

注意这里有一些坑点

前面说过:队尾+1等于队头时,队列为满

但是我用的是数组,不是链表队尾+1有可能会越界

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

如上图:rear+1 = 5,越界了

怎么办呢?可以采用取余数(%)的方法,即:(rear+1)%(k+1),让 rear+1 变回 0,达到循环的效果。

情况1:队尾+1越界了

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

(rear + 1) % (k + 1) = 0

front = 0

(rear + 1) % (k + 1) = front,说明循环队列已满。

情况2:队尾+1没越界

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

(rear + 1) % (k + 1) = 4

front = 0

(rear + 1) % (k + 1) != front,说明循环队列未满。

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

5. 队尾插入数据

这里需要一些操作,还是越界的问题,插入数据后队尾可能会越界,如下图:

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

rear 处插入数据后,rear 需要向后移动,导致越界

1)判断队列是否已满,满了是不能插入的,直接返回 false

2)在队尾插入数据

3)队尾++,可能会越界

4)依旧采用取余数的方法让队列循环起来,即:rear = rear % (k + 1)

//向循环队列插入一个元素。如果成功插入则返回真
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
    if (myCircularQueueIsFull(obj))
        return false;
    obj->a[obj->rear] = value;
    obj->rear++;
    obj->rear %= (obj->k + 1);
    return true;
}

6. 队头删除数据

删除数据后,队头也可能会有越界的情况,如下图:

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

删除 front 处的数据后,front 需要向后移动,导致越界

1)判断队列是否为空,空队列是不能删数据的,直接返回 false

2)删除数据很简单,直接让队头++即可

3)取余数避免越界:front = front % (k + 1)

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

7. 获取队头元素

情况1:队列为空

根据题意,返回 -1

情况2:队列不为空

直接返回数组中下标为 front 的元素即可

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

8. 获取队尾元素

情况1:队列为空

根据题意,返回 -1

情况2:队列不为空

  • 需要返回数组中下标 rear 的前一个元素(rear-1
  • 此操作可能会导致越界
  • 用取余数的方式避免越界:(rear + k) % (k + 1)

【数据结构】如何设计循环队列?图文解析(LeetCode),数据结构,数据结构,c语言,leetcode

如上图:这种情况下强行获取 rear 的前一个元素会导致越界

//获取队尾元素。如果队列为空,返回-1
int myCircularQueueRear(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
}

9. 销毁队列

销毁所有动态开辟的空间

//销毁循环队列
void myCircularQueueFree(MyCircularQueue* obj)
{
    free(obj->a);
    free(obj);
}

全部代码

//循环队列的结构
typedef struct
{
    int* a;     //一个数组
    int front;  //存放队头的下标
    int rear;   //存放队尾的下标
    int k;      //队列长度
} MyCircularQueue;

//开辟空间并初始化
MyCircularQueue* myCircularQueueCreate(int k)
{
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    //多开一个方便区分空和满
    obj->a = (int*)malloc(sizeof(int) * (k + 1));
    obj->front = obj->rear = 0;
    obj->k = k;
    return obj;
}

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

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

//向循环队列插入一个元素。如果成功插入则返回真
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
    if (myCircularQueueIsFull(obj))
        return false;
    obj->a[obj->rear] = value;
    obj->rear++;
    obj->rear %= (obj->k + 1);
    return true;
}

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

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

//获取队尾元素。如果队列为空,返回-1
int myCircularQueueRear(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
}

//销毁循环队列
void myCircularQueueFree(MyCircularQueue* obj)
{
    free(obj->a);
    free(obj);
}

本文完文章来源地址https://www.toymoban.com/news/detail-695449.html

到了这里,关于【数据结构】如何设计循环队列?图文解析(LeetCode)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构与算法】用队列实现栈&&用栈实现队列&&设计循环队列

    🌠 作者:@ 阿亮joy. 🎆 专栏:《数据结构与算法要啸着学》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、

    2024年01月20日
    浏览(32)
  • 数据结构刷题训练:设计循环队列(力扣OJ)

    目录 文章目录 前言 1. 题目:设计循环队列 2. 思路 3. 分析  3.1 定义循环队列  3.2 创建队列  3.3 判空和判满  3.4 入队  3.5 出队  3.6 取队头队尾数据  3.7 销毁队列  4. 题解 总结         当谈到队列数据结构时,很多人可能会想到普通的队列,即先进先出(FIFO)的数据结

    2024年02月13日
    浏览(35)
  • 【数据结构与算法分析】使用C语言实现队列的两种(带头结点与不带头结点)链式存储,并且给出一种循环队列的设计思想

      当我们编写程序时,经常需要处理各种数据结构。队列是一种常见的数据结构,它有着广泛的应用场景。队列的基本操作包括入队和出队,应用于模拟等待队列、消息队列、计算机缓存等场合。   在实际编程中,我们可以用不同的数据结构来实现队列。本文主要介绍了

    2024年02月08日
    浏览(47)
  • 数据结构--队列与循环队列

            队列是什么,先联想一下队,排队先来的人排前面先出,后来的人排后面后出;队列的性质也一样,先进队列的数据先出,后进队列的后出;就像图一的样子:  图1         如图1,1号元素是最先进的,开始出队时,那么他就是最先出的,然后12进队,就应该排在最

    2024年02月10日
    浏览(28)
  • 数据结构—循环队列(环形队列)

    循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且 队尾被连接在队首之后以形成一个循环 。它也被称为“ 环形缓冲器 ”。 循环队列的一个好处是可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素

    2024年02月11日
    浏览(29)
  • 【数据结构和算法】--队列的特殊结构-循环队列

    循环队列是队列的一种特殊结构,它的 长度是固定的 k ,同样是 先进先出 ,理论结构是 首尾相连的环形循环结构 。其理论结构大致如下: 具体结构描述可以参考 LeetCode : 622. 设计循环队列的题目要求,大致如下: 设计你的循环队列实现。 循环队列是一种 线性数据结构 ,

    2024年02月04日
    浏览(35)
  • 数据结构——循环队列详解

    目录 一、循环队列的定义 二、 循环队列的基本操作 三、循环队列的实现  1、循环队列的定义 2、循环队列的初始化  3、循环队列出队  4、循环队列入队  5、队列判空 6、 队列判满 7、取队头元素 8、输出队列  9、求队列长度  四、完整代码  五、小结  六、参考文献 一、

    2024年02月04日
    浏览(29)
  • 数据结构--循环队列、链队

    //循环队列数据结构 typedef struct { QElemType data[MaxQSize];//数据域 int front,rear; //队头队尾指针 }SqQueue; //链队结点数据结构 typedef struct QNode { int data;//数据域 struct QNode* next;//指针域 }QNode, * QueuePtr; typedef struct { struct QNode* front, * rear;//rear指针指向队尾 用于入队 front指针指向队头 用于

    2024年02月15日
    浏览(30)
  • 【数据结构】循环队列

    🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🐌 个人主页:蜗牛牛啊 🔥 系列专栏:🛹数据结构、🛴C++ 📕 学习格言:博观而约取,厚积而薄发 🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与

    2024年02月12日
    浏览(32)
  • 数据结构——循环队列的实现

    hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥 个人主页:大耳朵土土垚的博客 💥 所属专栏:数据结构学习笔记 💥对于数据结构顺序表、链表、堆有疑问的都可以在上面数据结构的专栏进行学习哦~ 有问题可以写在评论区或者私信

    2024年03月24日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包