数据结构刷题训练:设计循环队列(力扣OJ)

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

目录

文章目录

前言

1. 题目:设计循环队列

2. 思路

3. 分析

 3.1 定义循环队列

 3.2 创建队列

 3.3 判空和判满

 3.4 入队

 3.5 出队

 3.6 取队头队尾数据

 3.7 销毁队列

 4. 题解

总结


前言

        当谈到队列数据结构时,很多人可能会想到普通的队列,即先进先出(FIFO)的数据结构。然而,有时候我们需要一种更高效的队列实现方式,这就是循环队列。


1. 题目:设计循环队列

 题目描述:

数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

 题目链接:

设计循环队列https://leetcode.cn/problems/design-circular-queue/

2. 思路

        先来理解一下题意,首先队列的长度为定长k,其次就是队列可以循环利用空间。这里我们要思考一下是使用链表实现,还是使用数组实现。在设计这个环形队列的时候,我们肯定是要设计头和尾的入下图:

数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

         当前状态视为队列满,这时如果出队元素就会空出空间此时我们可以继续入队数据如下图:

数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

         后边满了以后再插入数据它可以绕回来,这就是循环队列。从front开始道rear结束就是队列的数据。或许有人会有疑惑:为什么不把尾指向最后一个元素,而是指向最后一个元素的后一个位置?

        这样是为了便于判断队列是否为空,我们举个例子,队列为空时front和rear是都指向开头的,如果插入一个数据,rear就要向后移动,不移动就无法判断队列是否为空。

接下来我们回到开始的问题,使用数组还是链表实现?

         我们依据上一个问题,知道rear指向的是队尾的后一个元素,那依据单链表的特性取队尾不好取。如果要好取尾就要用双向循环链表会好搞一些,当然还有其他的解决办法例如:多加一个变量size记录队列数据个数,rear指向队尾,这样也可以解决,但这样写代码会很容易让人误导,所以这里不推荐这样的方法。链表实现也是可以的,但相对数组的代码量就比较多了。使用数组实现也会简单方便的多。

 数组:

数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

         当rear+1==front时就是为满,由于它是一个循环队列,rear在末尾后再+1就会回到头,这里可以写成这样:front==(rear+1)%(k+1)(取值范围0~k),它要始终保持front与rear之间留有一个空。这里我们就使用数组来实现。

3. 分析

        依据上述的思路,我们使用数组来实现循环队列,通过上述的思路我们可以发现这个规律,出队就front向后走,入队就rear向后走。

 3.1 定义循环队列

typedef struct {
    int* a;
    int front;
    int rear;
    int k;
} MyCircularQueue;

        a用于存放数据,和顺序表类似,使用malloc开辟空间。front为队头,rear为队尾。

 3.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;
}

         这里和之前一样,我们仅仅是定义了队列的类型,并没有创建结构体变量,为了便于后续传参,这里我们使用malloc创建一个结构体变量。有了obj就可以通过它来找到结构体中的各个成员。注意我们还需要对数组a进行开辟空间。

 3.3 判空和判满

         这里我们先来实现判满和判空操作,上述思路中我们多开辟一个空间,用于判断满和空的情况,如果rear等于front就为空,如果rear+1等于front就为满。接下来我们来实现一下:

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return (obj->front==obj->rear);
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->front==(obj->rear+1));
}

         但这样写对吗?这样写是不对的,前边思路中提到:front==(rear+1)%(k+1)为了达到返回开头的目的,所以这里需要改写(也是为了防止rear+1越界)。

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return (obj->front==obj->rear);
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->front==(obj->rear+1)%(obj->k+1));
}

        这里可能就有人疑惑了,为什么rear需要模k+1返回,front就不需要呢?front也会走到尾啊。

这个当然是需要考虑的,这个操作是在出队操作时考虑的,在判满时可以不考虑,满的情况分为两种:

第一种:

数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

 第二种:

数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

 3.4 入队

 

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;
}

         入队操作非常简单,在入队之前先判断队是否满,如果满直接返回false(错误)。不为满就将rear位置入队数据,然后rear向后移动,这里为了便于rear返回,这里rear需要%=(k+1)。

过程如下:

 数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

 3.5 出队

 

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return false;

    obj->front++;
    obj->front %=(obj->k+1);
    return true;
}

         出队前要先判断队列是否为空,不为空就front++即可不需要任何修改(front开始到rear直接的为有效数据),为了便于front返回,这里可以使用取模,或者使用if语句判断,都可以。

 数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

 再次入队数据就会将原数据自动覆盖。

 3.6 取队头队尾数据

         取队头数据非常简单

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[obj->front];
}

         如果为空就直接返回-1,如果不为空就返回数组front下标的数据。重点在于队尾数据。

         一般情况队尾数据只需要rear-1就可以了,但是这里需要考虑rear为0的情况。如果rear为0,rear-1就越界非法访问了,我们需要的是rear返回到数组最后的位置。这里我们可以这样操作,既然我们是取模让rear达到返回到0,那我们在对rear取模之前先对rear+(k+1),这样rear取模后仍然可以取到下标为0的位置,-1就回到了最后的位置(减一后:(rear+k)%(k+1)结果为k)

 (rear+(k+1)-1)%k+1化简一下就是:(rear+k)%(k+1),代码实现:

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}

 3.7 销毁队列

        销毁队列也非常简单,先销毁啊数组,再销毁obj。

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

 4. 题解

 整体代码:

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->front==(obj->rear+1)%(obj->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;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return false;

    obj->front++;
    obj->front %=(obj->k+1);
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[obj->front];
}

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);
}

 力扣上边也是可以通过的。

 数据结构刷题训练:设计循环队列(力扣OJ),数据结构,算法,leetcode,c语言

         通过整体代码实现我们可以发现:数组实现循环队列需要特别注意边界问题,一不注意就会出现错误。


 

总结

        希望本博客能够帮助您更好地理解和应用循环队列,为您的学习和工作带来帮助。让我们继续探索数据结构的奥秘,不断提升自己的编程能力吧!文章来源地址https://www.toymoban.com/news/detail-645271.html

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

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

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

相关文章

  • 数据结构OJ:设计循环队列

    本题为LeetCode上的经典题目,题目要求我们设计一种循环队列,满足FIFO原则且队尾被连接在队首之后。 题目中介绍循环队列的好处是可以重复利用空间,所以我们很容易想到在初始化时即开辟指定大小的空间,之后便不需要再开辟空间,只需后续销毁即可。 首先我们要选择

    2024年04月17日
    浏览(49)
  • 【数据结构与算法】用队列实现栈&&用栈实现队列&&设计循环队列

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

    2024年01月20日
    浏览(32)
  • 【数据结构】如何设计循环队列?图文解析(LeetCode)

    LeetCode链接:622. 设计循环队列 - 力扣(LeetCode) 目录 做题思路 只开辟 k 个空间 多开一个空间 代码实现 1. 循环队列的结构 2. 开辟空间 3. 判断空 4. 判断满 5. 队尾插入数据 6. 队头删除数据 7. 获取队头元素 8. 获取队尾元素 9. 销毁队列 全部代码 设计循环队列,使用数组或链表

    2024年02月10日
    浏览(29)
  • 【数据结构与算法分析】使用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)
  • 【数据结构】循环队列

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

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

    //循环队列数据结构 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)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包