什么是队列
队列(Queue):具有一定操作约束的线性表
插入和删除操作:只能在一端插入,而在另一端删除
数据插入:入队列(AddQ)
数据删除:出队列(DeleteQ)
先来先服务
先进先出:FIFO
队列的抽象数据类型描述
类型名称:队列(Queue)
数据对象集:一个有0个或多个元素的有穷线性表。
操作集:长度为MaxSize的队列
Q
∈
Q
u
e
u
e
Q\in Queue
Q∈Queue, 队列元素
i
t
e
m
∈
E
l
e
m
e
n
t
T
y
p
e
item\in ElementType
item∈ElementType
Queue CreatQueue(int MaxSize): 生成长度为MaxSize的空队列;
int IsFullQ( Queue Q, int MaxSize ): 判断队列Q是否已满;
void AddQ( Queue Q, ElementType item): 将数据元素item插入队列Q中;
int IsEmptyQ( Queue Q): 判断队列Q是否为空;
ElementType DeleteQ( Queue Q): 将队列头数据元素从队列中删除并返回。
队列的顺序存储实现
队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量front以及一个记录队列尾元素位置的变量rear组成。
#define MaxSize <储存数据元素的最大个数>
struct QNode{
ElementType Data[ MaxSize ];
int rear;
int front;
};
typedef struct QNode *Queue;
一个平铺的工作队列:
Rear负责向队列中插入元素,Front负责删除。当队列为空时,Rear与Front相等
一个循环队列:
对于上面一种队列,可以通过Rear与Front是否相等来判断队列是否为空,但对于循环队列,Rear与Front相等时既有可能是空的,也有可能是满的。
解决方案:
a.使用额外标记:Size或者tag域
b.仅使用n-1个数组空间
(1)入队列
我们首先判断队列是不是满的。队列用一个结构指针PtrQ来表示
首先用rear+1求余,如果等于front表示队列满了。
void AddQ( Queue PtrQ, ElementType item)
{
if((PtrQ->rear+1)%MaxSize == PtrQ->front){
printf("队列满");
return;
}
PtrQ->rear = (PtrQ->rear+1)%MaxSize;
PtrQ->Data[PtrQ->rear] = item;
}
(2)出队列
ElementType DeleteQ( Queue PtrQ )
{
if(PtrQ->front == PtrQ->rear){
printf("队列空");
return ERROR;
}else{
PtrQ->front = (PtrQ->front+1)%MaxSize;
return PtrQ->Data[PtrQ->front];
}
}
队列的链式存储实现
队列的链式存储结构也可以用一个单链表实现。插入和删除操作分别在链表的两头进行;
队列指针front和rear应该分别指向链表的哪一头?
struct Node{
ElementType Data;
struct Node *Next;
};
struct QNode{ /*链队列结构*/
struct Node *rear; /*指向队尾结点*/
struct Node *front; /*指向队头结点*/
};
typedef struct QNode *Queue;
Queue PtrQ;
ElementType DeleteQ( Queue PtrQ )
{
struct Node *FrontCell;
ElementType FrontElem;
if(PtrQ->front == NULL){
printf("队列空"); return ERROR;
}
FrontCell = PtrQ->front;
if(PtrQ->front == PtrQ->rear) /*若队列只有一个元素*/
PtrQ->front == PtrQ->rear = NULL; /*删除后队列置为空*/
else
PtrQ->front = PtrQ->front->Next;
FrontElem = FrontCell->Data;
free( FrontCell ); /*释放被删除结点空间*/
return FrontElem;
}
其中 FrontCell = PtrQ->front
;就是找到队列头的位置,圈起来的就是FrontCell。