第4章栈和队列:顺序队——基本结构
4.6 顺序队
队列有两种存储结构,一种是顺序存储结构,另外一种是链式存储结构。
4.6.1 顺序队的结构
队列中数据元素的逻辑关系呈线性关系,所以队列可以像线性表、栈那样,采用顺序存储结构进行存储,即分配一块连续的存储空间来存放队列中的元素。又因为队列有队头和队尾,元素从队尾入队,从队头出队(先进后出),为了让此操作在 O(1)O(1)O(1) 时间复杂度上完成,因此,还要附设两个整型变量 front
和 rear
分别指示队头元素和队尾元素(分别称为“队头指针”和“队尾指针”)。
所以,用顺序存储结构表示队列,参考 4.2.1 顺序栈的存储结构以及上述引入的队头指针和队尾指针,可知队列的顺序存储结构应该包括:
base
:一个指向所分配连续内存空间起始地址的指针。它定义了队列的“物理边界”,是整个队列存在的基石。所有队列元素都存储在从base
开始的一段地址连续的空间中。front
:队头指针。它的核心语义是指向队列中第一个实际存在的元素(即最早入队、即将被出队的元素)。在非空队列中,base[front]
就是队头元素。rear
:队尾指针。它的核心语义通常是指向队列中最后一个实际存在元素的下一个位置(即下一个新元素入队时应存放的位置)。这是一种非常普遍和高效的约定,因为它简化了入队操作。
这三个元素共同构成了顺序队的完整状态描述符。通过 base
可以定位到存储空间,通过 front
和 rear
可以确定当前队列中有效数据在存储空间中的范围。
//队列的顺序存储结构
#define MAXQSIZE 100 //队列可能达到的最大长度typedef struct{QElemType *base; //存储空间的基地址int front; //队头指针int rear; //队尾指针
}SqQueue;
像这样,采用顺序存储结构的队列称为顺序队(Sequential Queue)。顺序队和之前学习过的顺序栈,都是逻辑线性关系在物理线性结构上的表示。
如图 4.6.1 所示,图中(a)表示的初始化创建了一个空队列(此队列的 MAXQSIZE=6
),此时队头指针和队尾指针都指向编号为 0 的存储单元,即:初始化创建空队列时,令 front = rear = 0
。
当有元素入队,即从队尾插入新的元素时,该元素插入到队尾指针 rear
所指的位置(编号为 0 的存储单元),而后队尾指针 rear
增 1
,指向下一个新元素入队时应存放的位置,如图 4.6.1(b) 所示。
当有元素出队,即从队头删除队头元素时,从当前顺序队中删除队头指针 front
所指示的元素,并将 front
增 1
,从而此指针继续指向队头元素的位置,如图 4.6.1© 所示。所以,在非空队列中,队头指针(front
)始终指向队头元素,而队尾指针(rear
)始终指向队尾元素的下一个位置(即下一个新元素入队应该存放的位置)。
按照上述操作,在图 4.6.1 所示顺序队中,相继有元素 J4, J5, J6J_4,~J_5,~J_6J4, J5, J6 入队,再执行 J3, J4J_3,~J_4J3, J4 出队,则得到图 4.6.1(d) 所示的结果。此时队尾指针已经指向了队列可能达到的最大值 MAXQSIZE = 6
,此状态称为“队满”。根据上述操作,可总结:
-
入队操作:先将元素放在队尾指针所指示的位置,然后将队尾指针
rear
增 1 。 -
出队操作:先取出队头指针所指示位置的元素,然后将队头指针
front
增 1 。 -
队空的条件:
front == rear
。 -
队满的条件:
rear == MAXQSIZE
。(注:
MAXQSIZE
是队列存储空间的最大值,如果用数组表示,则有效索引范围为 0 到 MAXQSIZE-1。当最后一个元素存入Q.base[MAXQSIZE-1]
后,Q.rear
会移动到MAXQSIZE
,此时队列已满。 )