【数据结构】队列

作者: Burnside | 来源:发表于2021-04-13 03:57 被阅读0次

本文更新于个人博客Burnside Blog

在数据结构中,最重要且最基础的两项就是栈与队列。一提到队列(Queue),相信大家都不陌生,它不像栈这个名字一样抽象,而是是一种很形象的结构,因为它本身就可以理解成一个队列。考虑我们排一路纵队在某个窗口办事,办完事的人一定是从队首离开队列,而想要进来办事的人一定是在队尾入队(假设一队人均素质优良,没有插队现象)。队列也是如此,它是一种先入先出的数据结构。

为了方便起见,我们不使用动态方式生成一个队列,或销毁一个队列,我们只考虑一个静态的队列的功能实现。队列中的元素可以是任何的用户自定义类型,为了方便起见,我们假设元素的类型为int,如需要别的类型,只需要灵活处理即可。接下来我们申请一块长度为MaxSize的连续内存来存储这个队列,这时它又被称为顺序队。

int Queue[MaxSize];

这样我们就获得了一个最多能存储MaxSize个元素的队列,在队列中,我们称队首为front,队尾为rear,接下来我们只需要模拟整个入队出队的过程即可。

int enQueue(int x){

    Queue[++rear]=x;

    return rear;

}

int deQueue(){

    return ++front;

}

不难理解,和栈类似,队列在入队操作发生时也只是将队尾的元素赋成新值,出队时将队首前移,这里要注意,队首和队尾在数组中存储的逻辑正好是反着的,也就是队尾的数组下标要比队首大,当然,如果一个队列为空,则队尾和队首的下标相同。

这样我们也可以写一个函数来判断一个队列是否为空。

int empty(){

    return front==rear;

}

这就是队列最简单的实现方式。但注意一点,为什么我们一开始说这个队列最多只能存储MaxSize个元素呢?因为我们发现,这个数组在不断入队出队的过程中,实际上用到的空间只有队首到队尾的这一点空间,而我们申请下来的MaxSize的空间很多是被浪费掉了的,再者,这个队列最多只允许我们进行MaxSize-1次的入队和MaxSize-1次的合法出队操作,因为在进行完这些操作后,队首和队尾的值就都等于MaxSize了,如果再进行入队出队就要访问到非法内存了。

难道队列就是一种如此低效的数据结构吗?并不是这样的,因为我们发明了一种循环队列,这种队列有一个特性,就是如果我的队尾或队首已经到MaxSize而我们想继续操作的时候,下一次的入队或合法的出队操作会使得队首或队尾回到数组下标为0的位置,将申请到的空间循环利用起来,具体实现如下。

入队

bool enQueue(int x){

    if((rear+1)%MaxSize==front) return false;

    Queue[rear=(rear+1)%MaxSize]=x;

    return true;

}

因为循环队列特殊的性质,也就是它的数组下标是循环出现的,我们很容易想到用取余(Mod)来实现数组下标的变换,在此函数中,返回值代表了入队是否成功。

出队

bool deQueue(){

    if(rear==front) return false;

    front=(front+1)%MaxSize;

    return true;

}

与入队相似。

取队首元素

int QueueFront(){

    return Queue[front];

}

此函数的功能是调用队首的元素,书中好像把它和出队操作写在一起了,我不是很推荐这样做,因为调用队首的元素不一定要让其出队。

判断队列是否为空

bool Empty(){

    return front==rear;

}

和普通队列一样判断就可以了。

经过这样的操作,我们就可以得到一个空间利用更高效的队列。当然,还有一种队列叫双端队列(Deque),是支持队首进队出队、队尾进队出队的特殊队列,写法和循环队列类似,读者可以在闲暇时间独立完成,书中貌似也有相关的代码。

书中还介绍了队列的链式存储,也就是链队,实现方式和顺序队类似,不再赘述。此外,还有队内元素保持单调性的单调队列,常用于对动态规划问题(Dynamic Programming,DP)的优化,常用于竞赛,感兴趣可以自行了解。

此外,可能会有部分读者表示我在实现普通队列的时候,没有考虑队列的非法操作(队满时入队,队空时出队),是因为那种队列的实现形式现在已经不用了(因为有更好的循环队列可以使用),因此没有详细处理细节,若想判断的话只需要在两个函数里分别加入if语句判断即可。

相关文章

  • 看图说话数据结构之二项队列(优先队列)——原理解析

    数据结构之二叉堆(优先队列)——原理解析,数据结构之二叉堆(优先队列)——java实现,数据结构之左式堆(优先队列...

  • MQ(message queue)

    是什么? 1.什么是队列? 队列是一种先进先出的数据结构。 数据结构 线性数据结构:常用的:线性表、栈、队列、串等...

  • 数据结构-队列(Queue)-FIFO

    数据结构-队列(Queue)-FIFO 队列的接口设计 双端队列-Deque 循环队列-CircleQueue 双...

  • Java数据结构和算法概览

    Java数据结构和算法概览 数据结构 线性数据结构:常见的有一维数组,线性表,栈,队列,双队列,串。 非线性数据结...

  • 刷穿剑指offer-Day20-队列I 队列的使用与基础题型!

    队列的介绍 队列(queue)是一种简单、常用的数据结构,在上一章栈的学习中,我们已经提到了队列这种数据结构。 队...

  • AQS源码浅析(6)——条件队列

    一、ConditionObject数据结构 简单回顾条件队列的数据结构,一个单链表。 条件队列只有在独占模式下才能...

  • C++数据结构探险——队列篇

    数据结构的原理 队列:先进先出(FIFO:first in first out) 普通队列: 环形队列: 以C++...

  • Handler精讲

    讲解本技术点之前需要准备的技术点回顾 队列数据结构 数据结构-队列(queue) - CSDN博客 Java中的T...

  • Queue

    什么是队列?队列是数据结构中比较重要的一种类型(是一种数据结构),它支持 FIFO,尾部添加、头部删除(先进队列的...

  • 队列

    队列 队列数据结构 队列是遵循FIFO (First In First Out, 先进先出, 也称先来先服务) 原...

网友评论

    本文标题:【数据结构】队列

    本文链接:https://www.haomeiwen.com/subject/dsfqlltx.html