四、栈与队列(下)

目录

1. 队列的定义

2. 队列的抽象数据类型

3. 循环队列

队列顺序存储的不足

循环队列定义

4. 实现循环队列的代码

循环队列的顺序存储结构

循环队列的初始化

循环队列求队列长度

循环队列的入队列操作

循环队列的出队列操作

5. 队列的链式存储及实现

链队列的结构

链队列的入队操作

链队列的出队操作

6. 总结


1. 队列的定义

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。

2. 队列的抽象数据类型

同样是线性表,队列也有类似线性表的各种操作,不同的就是插入数据只能在队尾进行,删除数据只能在队头进行。

3. 循环队列

线性表有顺序存储和链式存储栈是线性表,所以有这两种存储方式。同样,队列作为一种特殊的线性表,也同样存在这两种存储方式。

队列顺序存储的不足

若要保证下标为0的位置不为空,则出队需要将后面的元素全都往前移动,时间复杂度为O(n);

若采用双指针标志队头元素和队尾元素,不要求队头元素一定在下标为0的位置,则可能会发生“假溢出”。

循环队列定义

解决假溢出的办法就是后面满了,就再从头开始,也就是头尾相接的循环。我们把队列的这种头尾相接的顺序存储结构称为循环队列

继续入队:

 

此时问题:空队列时,front 等于 rear,现在当队列满时,也是front等于rear,那么如何判断此时的队列究竟是空还是满呢?

办法一:设置一个标志变量flag,当front == rear,且flag=0时为队列空,当front==rear,且flag=1时为队列满。
办法二:当队列空时,条件就是front=rear,当队列满时,我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。

对于第二种方法:

假设队列最大尺寸为QueueSize,那么队列满的条件是(rear+1)%QueueSize == front(取模"%"的目的就是为了整合 rear 与 front 大小为一个问题)。

当rear>front时,此时队列的长度为rear-front;

但当rear<front时,队列长度分为两段,一段是QueueSize-front,另一段是0+rear,加在一起,队列长度为rear-front+QueueSize;

因此通用的计算队列长度公式为:(rear-front + QueueSize)%QueueSize

4. 实现循环队列的代码

循环队列的顺序存储结构

循环队列的初始化

 

循环队列求队列长度

 

循环队列的入队列操作

 

循环队列的出队列操作

 

单是顺序存储,若不是循环队列,算法的时间性能是不高的,但循环队列又面临着数组可能会溢出的问题。 

5. 队列的链式存储及实现

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列

为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向终端结点,空队列时,front和rear都指向头结点。

  

链队列的结构

链队列的入队操作

 

链队列的出队操作

   


对于循环队列链队列的比较,可以从两方面来考虑,从时间上,其实它们的基本操作都是常数时间,即都为O(1) 的,不过循环队列是事先申请好空间,使用期间不释放,而对于链队列,每次申请和释放结点也会存在一些时间开销,如果入队出队频繁,则两者还是有细微差异。对于空间上来说,循环队列必须有一个固定的长度,所以就有了存储元素个数和空间浪费的问题。而链队列不存在这个问题,尽管它需要一个指针域,会产生一些空间上的开销,但也可以接受。所以在空间上,链队列更加灵活。
总的来说,在可以确定队列长度最大值的情况下,建议用循环队列,如果你无法预估队列的长度时,则用链队列。

6. 总结

栈和队列都是特殊的线性表,只不过对插入和删除操作做了限制。
栈(stack)是限定仅在表尾进行插入和删除操作的线性表。
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值