1. 队列的定义
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
2. 队列的操作
是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。
3. 循环队列
循环队列是把队列头尾相接的顺序存储结构。
通用计算队列长度的公式:
(rear - front + MAX_SIZE) % QueueSize
队列满的条件为:
(rear + 1) % QueueSize == front
3.1 循环队列顺序存储数据结构
typedef int QElemType;
typedef struct {
QElemType data[MAX_SIZE];
int front; //头指针
int rear; //尾指针,若队列不为空,指向队列尾元素的下一个位置
}SqQueue;
3.2 循环队列——初始化
Status InitQueue(SqQueue* Q)
{
Q->front = 0;
Q->rear = 0;
return OK;
}
3.3 循环队列求队列长度
int QueueLength(SqQueue Q)
{
return (Q.rear - Q.front + MAX_SIZE) % MAX_SIZE;
}
3.4 循环队列——入队
Status EnQueue(SqQueue* Q, QElemType e)
{
if ((Q->rear + 1) % MAX_SIZE == Q->front) //队列满
{
return ERROR;
}
Q->data[Q->rear] = e; //将元素e赋值到队尾
Q->rear = (Q->rear + 1) % MAX_SIZE; //rear指针向后移动一个位置,若到最后则转到数组头部
return OK;
}
3.5 循环队列——出队
Status DeQueue(SqQueue *Q, QElemType *e)
{
if (Q->front == Q->rear) //队列空
{
return ERROR;
}
*e = Q->data[Q->front]; //将队头元素赋值给e
Q->front = (Q->front + 1) % MAX_SIZE; //front指针向后移动一个位置,若到最后则转至数组头部
return OK;
}
3.6 循环队列的问题
循环队列存在着数组溢出的风险。
4. 队列的链式存储
4.1 定义
队列的链式存储结构,其实就是线性表的单链表。也被称为链队列。
4.2 链队列的结构
//结点结构
typedef struct QNode
{
QElemType data;
struct QNode* next;
}QNode, *QueuePtr;
//队列的链表结构
typedef struct
{
QueuePtr front, rear; //队头、队尾指针
}LinkQueue;
4.3 链队列——入队
Status EnQueue(LinkQueue *Q, QElemType e)
{
QueuePtr s = (QueuePtr)malloc(sizeof(QNode));
if (!s)
exit(OVERFLOW);
s->data = e;
s->next = nullptr;
Q->rear->next = s; //把拥有元素e新结点s赋值给原队尾结点的后继
Q->rear = s; //把当前的s设置为队尾结点,rear指向s
return OK;
}
4.4 链队列——出队
Status DeQueue(LinkQueue *Q, QElemType *e)
{
QueuePtr p;
if (Q->front == Q->rear)
{
return ERROR;
}
p = Q->front->next; //将欲删除的队头结点存于p
*e = p->data; //将欲删除的队头结点的值赋值给e
Q->front->next = p->next; //将原队头结点后继p->next赋值给头结点后继
if (Q->rear == p) //若队头是队尾,则删除后将rear指向头结点
Q->rear = Q->front;
free(p);
return OK;
}