队列是一种先进先出的线性表。要求所有数据从队列一端进入,从队列另一端离开。
在队列中,允许插入数据的一端叫做队尾rear;允许数据离开的一端叫做队头front;
定义一个队列:
typedef struct QNode{
QelemType data;//链队列结点中的数据域
struct QNode *next;//链队列结点中的指针域
}QNode, *QueuePtr;
typedef struct{
QueuePtr front;//队头指针,等价于QNode *front
QueuePtr rear;//队尾指针
}LinkQueue;
QNode为队列元素的类型,QueuePtr为指向QNode类型元素的指针类型,等价于QNode*。
创建一个队列:
1)在内存中创建一个头结点,该结点不是用来存放数据的,而是为了操作方便人为添加;
2)将队列的头指针和尾指针都指向这个生成的头结点,此时队列中没有任何队列元素,该队列为空队列;
initQueue(LinkQueue *q) {
q->front = q->rear =(QueuePtr)malloc(sizeof(Qnode));
if(!q->front) exit(0);
q->front->next = NULL;
}
入队列
EnQueue(LinkQueue *q,ElemType e) {
QueuePtr p;
p = (QueuePtr)malloc(sizeof(QNode));
if(p==NULL) exit(0);
p->data = e;
p->next =NULL;
p->rear->next = p;
q->rear = p;
}
出队列
DeQueue(LinkQueue *q,ElemType e) {
//如果队列不为空,删除q的队头元素,用e返回其值
if(q->front ==q->rear) return;//队列为空,返回
p = q->front->next; //p指向队列的第一个元素
*e = p->data; //将队首元素的数据赋值给e返回
q->front->next = p->next; //删除头结点
if(q->rear == p) q->rear =q->front; //如果此时队列为空,则修改队尾指针
free(p);
}
销毁一个队列
DestroyQueue(LinkQueue *q) {
while(q->front) {
q->rear = q->front->next;
free(q->front);
q->front = q->rear;
}
}
补充:
对于一般的链队列,只要队列非空,其队头指针front和队尾指针rear都不会发生改变,只是头结点的next指针和队尾的前一个结点的next指针会发生变化,而且链队列的长度也会随着入出队列元素而不断变化。rear指针始终指向队尾元素的下一个空间。
循环队列可以作为缓冲池存储结构来存放数据。
循环队列实际上用顺序表模拟出来的逻辑上循环,物理存储空间呈线性的队列数据结构。