当前位置:网站首页 > 编程语言 > 正文

环形队列循环队列一样么(环形队列的实现)



之前我们学习过数据结构中的栈和队列,详情可点击这里进行查看🥳🥳,队列是一种先进先出的结构,但是我们之前讲的队列都是类似于线性的物理结构,这次我们所介绍的队列则是一直类似于环状的循环结构,它依旧保持着队列的特性——先进先出。

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

循环队列的实现应该支持如下操作:

题目链接——大家也可以在学习完栈和队列后自己尝试写一写。

首先根据题目要求,队列长度为k,所以一开始我们要使用malloc开辟k个节点的空间,而不是和之前的队列一样在增加数据时再开辟节点,循环队列的长度是固定的,最开始就已经开辟好了,所以不需要再在使用时开辟节点空间。

如上图所示,已经在内存中开辟了完整的空间,最开始队列的头尾指针都指向开始的位置,每加一个元素,rear指针也就是尾指针的位置就往后挪动一位,删除数据就把头指针front往后挪一位,当rear指针指向最后一个元素时,队列满了,此时的判断条件应该时rear->pNext = front; 也就是说rear的下一个位置是front,如下图所示:

思考一下:rear指向的是尾部的元素还是尾部元素的下一位呢? 1.zz如果rear指向的是尾部元素,那么在实现时判断循环队列是否满的条件就是rear->pNext = front; 但是💥💥判断循环队列是否为空的条件就不简单是rear == front,因为在插入第一个元素时,front指向该元素,rear指向最后一个元素也就是刚刚插入的第一个元素,因为此时队列中只有一个元素,此时rear == front ,但此时循环队列不为空; 2.但如果循环队列的rear指针指向尾部元素的下一个就好判断了,为空时rear==front; 不为空时rear!=front;即使只有一个元素,rear也不指向该元素而是指向该元素的下一位,但是💥💥在判断循环队列是否满时又出了问题,当循环队列满了的时候,rear指向队尾元素的下一个,此时rear指向front,这不就和为空的条件冲突了吗? 解决办法: 🥳🥳1.针对第一种rear指向尾部元素: 可以考虑在创建队列时不单单创建front(队列头指针)和rear(队列尾指针)这两个元素,可以增加一个 size来记录此时队列里的节点个数; 🥳🥳2.针对第二种rear指向尾部元素的下一个位置: ①也可以增加一个size来记录存放的节点个数 ②考虑多开辟一个节点的空间(需要k个节点就开辟k+1个节点的空间),剩下一个节点的位置不存放数据,是专门用来防止队列满时rear的下一个元素指向front,如果增加一个空闲的位置,队列满时rear的下一个位置就不再指向front;

💫💫在决定选哪种方法之前,我们先要考虑一下是使用链表来实现还是使用数组也就是顺序表来实现循环队列;当然这里土土会将两种方法都写下来,并和大家一起分析两种方法的优劣之处,以便大家选择合适和喜欢的形式🥰🥰(对于顺序表链表有疑问的可以在土土的数据结构专栏里—— 进行查看复习哦~)

✨✨经过我深思熟虑(其实是随便选的😎😎),决定采用第一种rear指向队尾元素的方法来实现,虽然第二种方法我给出了两种解决办法,但是我发现第一种方法在求队尾元素时异常的方便,只要return rear->data就好了,如果是第二种rear指向队尾元素的下一个,那么我们求队尾元素时还需要找到rear的前一个指针,如果我们使用双向链表就会很简单,但这里我选择使用单链表来实现;

3.1设计队列结构

前面我们提到过设计队列时考虑加上一个size记录存放节点个数以便判断队列是否为空

队列的节点和单链表一致:data存放数据;pNext存放下一个节点指针

3.2构造队列(k个节点)

MyCircularQueue(k): 构造器,设置队列长度为 k

这里我们除了需要malloc k个节点外,还需要将这k个节点串联在一起使他们物理结构上成环(对于malloc有疑问的可以查看土土的博客——)代码如下:

调试时我们发现成功构造了循环队列:

后面pNext又回到了最开始的位置说明我们链接成功啦🎉🎉🎉

我们还将队列的头尾指针与开辟的k个节点做了连接,使得队列的头尾指针指向了k个节点的地址,并将size初始化为0;

3.3 向循环队列插入一个元素

myCircularQueueEnQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。代码如下:

🥳🥳 ①这里首先要判断队列是否满了,如果满了则不能再插入元素直接返回false; 🥳🥳② 其次因为我们的rear是指向最后一个元素的所以在插入元素时要分两种情况来看——一种只有一个节点的情况头尾指针都需要变;另一种存放多个节点的情况只需要改变尾指针; 🥳🥳③此外增加元素size++; ✨✨④最后判断循环队列是否为空函数在下面介绍;

3.4判断循环队列是否为空

myCircularQueueIsEmpty(): 检查循环队列是否为空。

3.5判断循环队列是否满了

myCircularQueueIsFull(): 检查循环队列是否已满。

这里我们看到我打了一个?,obj->size ==k是不能判断队列是否满了的,因为k并没有作为参数传给判满函数,我们根本不能使用k,k 只在构造队列时出现过; ✨✨我们还发现这里出现了只有一个节点的情况,因为当队列构造时传的k == 1,也就是整个循环队列只有一个节点,那么无论队列中是否有节点rear的下一个位置始终时front,此时该判断条件不成立,所以我们需要将该情况单独列出来,当rear->pNext 等于front时并且obj->size 不等于0时才能判断队列满了return true;其他情况return false;

3.6从循环队列中删除一个元素

myCircularQueueDeQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。注意队列先进先出,是头删。

这里和插入一个元素一样也要分两种情况,size对应-1;就不过多赘述

3.7 从队首获取元素

myCircularQueueFront: 从队首获取元素。如果队列为空,返回 -1 。

3.8获取队尾元素

Rear: 获取队尾元素。如果队列为空,返回 -1 。

3.9销毁循环队列

3.10结果如下

4.1设计队列结构

前面我们提到过设计队列时考虑加上一个size记录存放节点个数以便判断队列是否为空

这里采用一个结构体封装,并记录数组的首尾下标,并保留一个k来记录k值,以便后面使用。

4.2构造队列(k+1个节点)

MyCircularQueue(k): 构造器,设置队列长度为 k

这里注意开辟了(k+1)个节点空间,采用的是前面说的第二种情况,rear指向最后一个元素的下一个位置。

4.3向循环队列插入一个元素

myCircularQueueEnQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。代码如下:

这里也分两种情况来插入,💥💥此外还要注意插入元素之后rear要++,但是如果rear超过数组的长度k+1就会造成越界访问,所以这里提供了一个方法:每次rear++之后再与k+1取模运算,这样就可以得到小于等于k的值,不会造成越界访问。

4.4判断循环队列是否为空

myCircularQueueIsEmpty(): 检查循环队列是否为空。

因为rear指向最后一个元素的下一个元素,所以当rear等于front时,数组为空,此时一个数据也没有插入。

4.5判断循环队列是否满了

myCircularQueueIsFull(): 检查循环队列是否已满。

数组并非像链表那样有pNext指针指向下一个节点,链表可以形成天然的循环结构,而数组却要依靠首尾下标来模拟实现,如图所示有两种情况:

当删除节点时只需将front++即可,所以front位置可能不是0;

4.6从循环队列中删除一个元素

myCircularQueueDeQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。注意队列先进先出,是头删。

注意这里front也是一样,在+1后可能大于k造成越界,所以要进行取模运算。

4.7 从队首获取元素

myCircularQueueFront: 从队首获取元素。如果队列为空,返回 -1 。

4.8获取队尾元素

Rear: 获取队尾元素。如果队列为空,返回 -1 。

这里要注意本来应该返回rear-1;因为rear指向尾节点的下一位,但是如果rear值为0时,再-1就变成-1了,也会造成越界访问,所以也要进行取模运算(rear-1+k+1)%(k+1),即可,因为数组有k+1个节点所以要+(k+1)并%(k+1)

3.9销毁循环队列

3.10结果如下:

链表来实现循环队列有一个好处就是形成了天然的环形结构,对应数组实现循环队列则需要front,rear不断进行取模运算以防越界; 但是链表实现需要手动将开辟的节点链接在一起,数组则不一样它一开辟就是地址连续的一段空间; 其他的实现链表和数组都差不多; 以上就是循环队列的实现啦~ 大家有什么疑问可以写在评论区或者私信我哦~ 完结撒花~🥳🥳🎉🎉🎉

到此这篇环形队列循环队列一样么(环形队列的实现)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 倍思蓝牙耳机怎么断开连接(倍思蓝牙耳机怎么断开连接电脑)2025-01-18 20:36:05
  • 来自远方的小说 百度网盘(来自远方的小说txt百度云)2025-01-18 20:36:05
  • 无法访问samba共享目录(samba访问不了共享文件夹)2025-01-18 20:36:05
  • ip网址域名查询(网站域名解析ip)2025-01-18 20:36:05
  • nvme接口引脚定义(nvme接口长什么样子)2025-01-18 20:36:05
  • 结构游戏的基本结构(结构游戏的基本结构包含)2025-01-18 20:36:05
  • u盘虚拟光驱删除(u盘虚拟光驱删除方法)2025-01-18 20:36:05
  • 本机设置安装(安装设置怎么弄)2025-01-18 20:36:05
  • git的用法(git的基本用法)2025-01-18 20:36:05
  • 传输网页使用的协议是什么(浏览器传输网页使用的协议是)2025-01-18 20:36:05
  • 全屏图片