数据结构之队列篇总结

队列是一种比较重要的数据结构。它只允许在一端插入,然后在另一端出队的线性表,因此具有先进先出的特性。我们一般称插入端为队尾,出队端称为队头。

队列的顺序结构

       顺序存储结构用数组来实现,通过给定数组的大小来确定队列的容量。如下图所示,rear用来指向队尾元素,初始值化一个空队列的时候可以将rear指向-1,然后随着不断往队列中增加或删除元素就相应地将rear的值进行增加或减少,让其始终指向队尾的元素,当rear的值为-1时,表示当前队列为空。                     

数据结构之队列篇总结_第1张图片

       但是这种方式来描述队列存在一个问题。就是每次往队列中增加或删除一个元素,队列里面的元素都要进行相应的移动,就会造成效率低下。对其的处理方式是:在设置一个位置变量front,入队时rear加1,出队时front加1,并且约定front指向队头元素的前一个位置,rear指向队尾元素的位置,这约定目的可以方便计算长度(rear-front等于队列的长度),如下图所示。

数据结构之队列篇总结_第2张图片

       按照上述的处理方式,往队列中不断地增加或者删除元素,可想而知整个队列会高端移动过去。当不断插入到数组中下标的最大,表示此时的数组的空间就用尽了,尽管数据的低端因为期间有元素出队就会产生空闲的空间,这就会造成一个“假溢出”问题。

数据结构之队列篇总结_第3张图片

       为了解决“假溢出”造成空间浪费的问题,处理的方式是:设计将数组形成一种头尾相连的环形结构,即当插入元素到达数组最大端下标时,下一个插入元素会延续从数组下标最小端开始进行插入。在设计程序中也很好实现,我们可以加个条件进行判定是否rear已经指向数组下标最大值,然后下一个插入就让rear从数组下标最小开始计数;或者可以通过让当前的rear的值和数组的尺寸大小进行求余运算,使得rear的值等于数组储存大小时,求余运算等于0,重新从数组的0下标开始进行插入,如下图所示。

数据结构之队列篇总结_第4张图片

       那应该怎么判断当前的队列是否已经满了呢?为了方便设计及处理,我们可以浪费一个数组元素的元素的空间。使得当前的rear值+1=front值,就表示该队列已经满了。如上图表示当前的队列为满。

       那为什么不直接判定rear值=front值来表示队列为满呢,因为如果这样判定的话,当队列为空时,同样满足rear值=front值,我们就要将这两种情况进行区分。就如同我们很多时候设计链表时会设置一个头结点一样,并不使用它存储数据,有了头结点可以使插入删除等操作不用区分是否是表头的情况,操作更方便。

队列的链接结构

       通常用单链表来表示,根据队列的先进先出特性和操作上的方便,一般设置头指针指向链队列的头结点,队尾指针指向终端结点,如下图所示。

数据结构之队列篇总结_第5张图片

两个主要的操作:

入队操作

根据上面描述构造的队列,初始化空队列时,使front和rear都指向头结点,因此判定front=rear即为空队列。由于插入操作只考虑在链表的尾部进行和链队列带了头结点,在插入元素的过程中无论是否空队列都是一样的,如下图所示。

数据结构之队列篇总结_第6张图片

出队操作

删除操作只考虑在链表的头部进行,默认队列中有元素才进行出队操作,但是要分析两种情况:

1.队列长度等于1的时候

2.队列长度大于1的时候

p指针的初始化为front->next。当队列长度等于1的时候,即p的描述为p->next==NULL,此时的处理是:暂存队头元素,然后将rear=front即可;当队列长度大于1的时候,此时的处理是:暂存队头元素,然后将front->next=p->next即可。

数据结构之队列篇总结_第7张图片

        初始时循环队列必须确定一个固定长度,所以会有元素个数的限制和浪费空间的问题,链队列不会有溢出的问题,但是每个元素都需要一个指针域,从而也会产生结构性开销。

        作为一般规律,队列元素变化较大时,优先考虑链队列,反之采用循环队列。顺序结构和链接结构的选择也要根据具体情况来确定,所以不能一概而论。

        the end~

你可能感兴趣的:(数据结构,队列)