数据结构:队列

先来一张总体结构图

循环队列是顺序队列的一个延申

队列的定义:

和栈对比起来,栈不是先进去的后出来嘛?队列刚好反着来,先进去的先出来,相当于是什么呢?栈只有一个出口,队列呢?两个出口,通风的。

同样的,队列的实质也是一个受限制的线性表!!!记住了,也是线性表的一种!

他呢就可以在两头操作了,不过两头的操作是不能重叠的,比如只能在一端进行插入,另外一端只能进行删除,不能再同一端又插入又删除。

涉及到的几个概念:

队头:也就是允许删除的那一端

队尾:允许插入的那一端

队列的存储结构:

顺序存储队列:

前面的顺序栈和顺序表都可以用数组来实现,同样的,在这里也可以用数组来实现顺序队列。

假溢出:

我们看到上面这个图:什么是假溢出呢?当5这个元素加进来后,我们看到实际上这个队列已经满了,为什么?因为队列是不能在删除的一端进行插入的,所以这个时候是明明还有存储空间的,但是已经无法继续装填新的元素了,这种就叫做假溢出!

我们看到了上面有两个指针,一个是front(队头指针),一个是rear的(队尾指针)这里注意了,队头指针是指向的第一个元素,队尾指针是指向的队尾元素的后面一个位置。

循环队列:(重点)

循环对列是由顺序队列进化而来,所有拥有顺序对列的一些特性

为了解决假溢出这个情况,我们就可以使用循环队列,让他们首尾相接。也就是说,我们把这种首尾相连的顺序队列就叫做循环队列,注意定义,是首尾相连的顺序队列。

这里的入队和出队操作显然就和上面的顺序队列不一样了,因为这里是循环的,但是又没有链表那种专门拿一块空间来存放其他节点的位置信息,所以这里实际上用到了这两个公式。

rear表示队尾的指针,一般是指向队尾元素的后一个位置,这样能防止在只有一个元素的时候,队首指针和队尾指针相互重叠了,就不好办了。注意一点,入队的时候,肯定是先给这个位置赋值,然后再将指针向后移动一位的嘛。

MaxSize表示的是数组的容量,也就是最多能存放的元素个数。我们在这里通常用取余才计算元素插入的位置。为什么是取余哈,我们都已经知道了,这里是循环队列,已经变成了循环,相当于是首尾相连了,如果还是传统的+1,很显然是没有办法来循环的。如果我们是取余,那就可以进行循环定位了,比如说,我们有一个数组,容量是4,下标从零开始就是0 1 2 3,那我现在已经在2这个下标上有元素了,要在3这个位置插入元素,怎么办呢?rear=(rear+1)%maxSize。计算就是(3+1)%4=0得出来,rear的新位置是0,但是他是指向的插入元素的后一个元素,而这里很明显就是进行了一次下标的循环了,所以往上退一个下标就应该是3,所以这个元素插入的位置应该是3。和我们预期的是一样的。

但是这样又会出现新的问题,什么问题?你会发现,循环队列是空的时候,rear指针和front指针是相等的,也就是队首指针和队尾指针相等,但是呢,这样一来,当队列满了的时候,也就是元素装满了,不能再继续入队了的时候,这两个指针也是相等的,那这样就出现了歧义了,到底什么时候是空队,什么时候是满队呢?显然这样就无法判断了。

解决办法:

方法一:设置一个标志位flag,当出队的时候我们让他等于0,入队的时候等于1,那这样就很显然了,如果是flag=1引起的两个指针相等,那很显然就是队列满了嘛,但是如果flag=0,那就肯定是出队引起的两个指针相等,既然是出队,那肯定不可能满队嘛,那就只有空队了。

方法二:我们把两个指针相等的情况只视为是队列空的情况,那这个时候我们就有一个限制了,怎么办呢?要让数组中始终空出来一个元素,也就是说,不能然队列真真实实的满队,因为那样肯定会造成两个指针相等,我们现在就这样办,当队列中只空出来一个位置的时候,我们就直接认为已经是满队了,不能继续插入元素了。那既然这样,满队的时候又是怎么判断的?

只要两者指针的关系满足上面这个公式就可以了,其实就是两个指针再位置关系上相差1,注意了,这里的1不是基本的我们的+1和-1来确定的,因为这里已经是循环了,所以如果你队首指针指向第一个元素,队尾指针指向最后一个位置,那他们再数值上肯定是相差大于1的,我们这里说的相差1,一定是通过这个公式计算出来的,通过取余计算的。

队列中的元素个数,我们通过下面这个公式来计算

链式队列:

队列的链式存储结构其实就是线性表中的单链表,但是因为队列的性质,就之能在一头删除一头插入而已。

注意一点的是,链队的队尾指针就是指向队尾元素的,不是队尾元素的下一个位置,要记住,链式和顺序的结构已经不一样了。

对于只有一个元素的链队,出队的时候需要注意一下,这里不要误会,第一个H是头节点,它是没有具体有效数据的。别忘了链表是怎么样的了。

ok,这里需要注意什么呢?如果链队元素不止一个,那很简单了,把队首元素删除就行了,但是只有一个元素的时候,直接删除,这个rear指针要指向那里呢?对吧,这样直接删除是会出错的,记得我们前面说的,队列的判空条件是什么?就是两个指针相等,所以这个时候应该要先把rear指针移动到front指的那个位置来,再才能删除这个元素。

双端队列:

双端队列呢,他喵的他就是队列的一个变种,我们都知道,队列是只能在一端进行插入,另外一端进行删除的,而双端队列呢,它两端都能进行插入和删除。所以这个时候还给他叫队首和队尾已经不合适了,我们给他取了一个新名字,叫前端和后端。niang的,搞得跟web开发一样。。。

如果对双端队列的两边进行一些限制,那就会又上面的图中的这种双端队列。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值