队列是一种先进先出的线性表。要求所有数据从队列一端进入,从队列另一端离开。
在队列中,允许插入数据的一端叫做队尾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指针始终指向队尾元素的下一个空间。
循环队列可以作为缓冲池存储结构来存放数据。
循环队列实际上用顺序表模拟出来的逻辑上循环,物理存储空间呈线性的队列数据结构。