1.队列的基本定义
队列 (Queue) :也是运算受限的线性表。是一种先进先出 (First In First Out ,简称 FIFO) 的线性表。只允许在表的一端进行插入,而在另一端进行删除。
队首 (front) :允许进行删除的一端称为队首。
队尾 (rear) :允许进行插入的一端称为队尾。
队列中没有元素时称为空队列。在空队列中依次加入元素 a 1 , a 2 , …, a n 之后, a 1 是队首元素, a n 是队尾元素。显然退出队列的次序也只能是 a 1 , a 2 , …, a n ,即队列的修改是依先进先出的原则进行的
2.队列的顺序存储结构
顺序存储结构存储的队列称为顺序队列.和顺序表一样,用一个一维数组存.对头在数组的低下标端,队尾设在高下表端.队头,队尾指针值是数组元素的下标.对头指针始终指向对头结点的前一个结点位置,初始值为0.队尾指针是指向队尾结点位置,初始值也为0.
3.队列初始条件、队列满条件、队列空条件分别是什么
队列初始条件:队头指针=队尾指针=0
队列满条件:队尾指针=m(设队列当前容量为m)
队列空条件:队头指针=队尾指针
4.顺序存储队列与站的不同之处是什么?
与栈不同的是:队列元素的出列是在队头,即下标为0的位置,意味着一个元素出队后,队列中的其他所有元素都得向前移动,以
保证队列的队头,也就是下标为0的位置不为空,该时间复杂度为O(n).
在现实中也是如此,一群人排队买票,前面的人买好了离开,后面的人就要全部向前一步,补上空位。
---- 但是为什么出队列时一定要全部移动呢?如果不去限制队列的元素必须存储在数组的前n个单元的这一条件,出队的性能就会大
大增加。也就是说,队头不需要一定在下标为0的位置。
---- 为了避免当只有一个元素时,队头和队尾重合使处理变得麻烦,所以引入两个指针,front指针指向队头元素,rear指针指向队尾
元素的下一个位置,这样当front==rear时,此队列不是还剩一个元素,而是空队列。
5.当空队列时,front==rear,而当队列满时,还是front==rear,那么如何判断此时的队列究竟是空还是满呢?
办法一:设置一个标志变量flag,当front==rear且flag=0时为队列空,当front==rear且flag=1时为队列满。
办法二:当队列空时,条件就是front=rear,当队列满时,我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有
一个空闲单元。队列满的条件是:(rear+1)%QueueSize==front(队列的最大尺寸是QueueSize)
---- 当rear>front时,此时队列的长度为rear-front.
---- 当rear<front时,队列的长度分为两段,一段是QueueSize-front,另一段是0+rear,总长度是:rear-front+QueueSize
因此,通用的计算队列长度公式是:(rear-front+QueueSize)% QueueSize
- #include <iostream>
- using namespace std;
- #define OK 1
- #define ERROR 0
- #define MAXSIZE 100
- typedef int Status;
- typedef int QElemType;
- typedef struct
- {
- QElemType data[MAXSIZE];
- int front; //头指针
- int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
- }SqQueue;
7.队列的链存储结构是什么
链存储结构存储的队列称为链队列.队头指针指向链队列的头结点,头结点的指针域若为空,则为空队列;若不为空,则为指向队首结点的指针.
链队列设有一个队头指针,其值指向队列的头结点.也是唯一地标示一个链队.设置一个队尾指针方便插入结点.队头指针和队尾指针都是指针型变量.
链队列没有容量的限制,所以在可用的存储空间范围内,一般不会出现上溢问题,也不存在如顺序队列的假溢出问题.
9.循环队列长度是如何运算的?
- /* 返回Q的元素个数,也就是队列的当前长度 */
- int QueueLength(SqQueue& Q)
- {
- return (Q.rear-Q.front+MAXSIZE) % MAXSIZE;
- }
循环队列的使用较为广泛,主要优点有两个:一是相较于普通数组,提供了先进先出的概念,在使用功能上进行了拓展,二是在普通队列的元素操作方式上进行了改进,增加了空间的使用效率,虽然仍然浪费了一个存储单位的空间,但是相比之前已经优化了太多。