数据结构之-队列

队列

什么是队列?

队列一种特殊的线性表,也是常见的一种数据类型。特殊之处在于它只能在表的前端(front)进行删除,而在表的后端(rear)进行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头

队列又称为先进先出(FIFO—first in first out)线性表。

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

顾名思义,顺序存储采用数组的方式,而链式存储采用链表的方式。

顺序存储的队列又分为顺序队列循环队列

01 顺序队列

首选说一下顺序队列的坏话,顺序队列在入队列的时候可以保持O(1)的时间复杂度,而在出队列的时候队头后边的元素需要依次往前移动,以保证队头不为空,时间复杂度就变成了O(n);

为什么出队列时一定要全部移动呢,那么我们是否可以解决出队列所带来的问题呢,当然可以。

如果不去限制队列的元素必须存储在数组的前n个单元这一条件,出队的性能就会大大增加。这也就意味着队头不一定位于index=0的位置了。

假设是长度为5的数组,初始状态,空队列如所示,front与 rear指针均指向下标为0的位置。然后入队a1、a2、a3、a4, front指针依然指向下标为0位置,而rear指针指向下标为4的位置。

《数据结构之-队列》 image

出队a1、a2,则front指针指向下标为2的位置,rear不变,如下图所示,再入队a5,此时front指针不变,rear指针移动到数组之外。嗯?数组之外,那将是哪里?

《数据结构之-队列》 image

如上图所示,添加a5元素之后,rear已经无家可归了,于此同时0和1位置的空间却被拜拜浪费了,这个中情况被称之为假溢出

为了解决假溢出的情况也就引出了我们接下来要讲的循环队列

02 循环队列

接着上图的来讲,为了把无家可归的rear有个好的落脚点,我们就把它放置在index=0的位置。

《数据结构之-队列》 循环队列-图1

但是如果继续进行入队操作的话,比如继续插入a6、a7,则rear指针就与front指针重合,同时指向下标为2的位置。

《数据结构之-队列》 循环队列-图2

此时问题又出来了,我们刚才说,空队列时,等于rear,现在当队列满时,也是from等于rear,那么如何判断此时的队列究竟是空还是满呢?

办法一是设置一个标志变量flag,当front == rear,且flag = 0时为队列空,当front == rear,且flag= 1时为队列满。

办法二是当队列空时,条件就是from = rear,当队列满时,我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。 如下图所示,我们就认为此队列已经满了,也就是说,我们不允许上图情况出现。

《数据结构之-队列》 循环队列-图3

在第二种情况下,由于rear可能比front大,也可能比front小,所以尽管它们只相差一个位置时就是满的情况,但也可能是相差整整一圈。所以若队列的最大尺寸为QueueSize,那么队列满的条件是(rear+1) %QueueSize == front (取模“%的目的就是为了整合rear与front大小为一个问题)。

比如上面这个例子, QueueSize = 5,当 front=0,而 rear=4, (4+1) %5 = 0,所以此时队列满。再比如,front = 2而rear =1。(1 + 1) %5 = 2,所以此时 队列也是满的。而对于下图, front = 2而rear= 0, (0+1) %5 = 1,1!=2,所以此时队列并没有满。

《数据结构之-队列》 循环队列-图4

另外,当rear > front时,此时队列的长度为rear—front。但当rear < front时,队列长度分为两段,一段是QueueSize-front,另一段是0 + rear,加在一起,队列长度为rear-front + QueueSize,因此通用的计算队列长度公式为:

(rear—front + QueueSize) % QueueSize

从上面的图我们不难看出顺序存储存在着数组可能会溢出的问题,所以也就引出了链式存储结构。

链队列

在链队列中,队头指针指向头结点,队尾指针指向终端结点,一个普通的链队列如下图所示:

《数据结构之-队列》 image

当队列为空时,front和rear都指向头结点。

Conclusion:

时间复杂度空间复杂度
顺序队列入队列O(1),出队列O(N)必须要申请固定的长度,空间上浪费。
循环队列入/出队列O(1)必须要申请固定的长度,空间上浪费。
链队列入/出队列O(1)在空间上,链队列更加灵活。

参考:

  1. 队列顺序存储结构的不足
  2. 链队列:队列的链式存储结构
    原文作者:我是吸血鬼
    原文地址: https://www.jianshu.com/p/46fed55ba642
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞