一.队列的类型定义
队列的操作与栈的操作类似,不同的是,删除在表的头部(即队头)进行。特点是“先进先出”。
二.队列的顺序表示和实现
- 顺序分配的队列中头指针(Q.front)、尾指针(Q.rear)和元素之间的关系如下图:

假设当前队列分配的最大空间为MAXQSIZE(图中为6),在d所示的状态不可再继续插入新元素,否则会出现溢出现象,实际上此时队列的可用空间并未占满,这种现象称为“假溢出”。这种现象的出现,主要是由“队尾出队,队头出队”的操作造成。
1.循环队列
为了解决“假溢出”问题,将顺序队列变为一个环状空间,即“循环队列”。 头、尾指针以及队列元素之间的关系不变,在循环队列中,头、尾指针“依环状增1”的操作可用“模”运算来实现,通过取模,头指针和尾指针就可以在顺序表空间内以头尾衔接的方式“循环”移动。
循环队列中头指针(Q.front)、尾指针(Q.rear)和元素之间的关系如下图:

- a. 队头元素是J5,在元素J6入队之前,Q.rear的值为5,当元素J6入队之后,通过“模”运算,Q.rear = (Q.rear+1) % MAXQSIZE; 即Q.rear = 0;此时不会出现“假溢出”
- b. J7,J8,J9,J10相继入队,队满,此时头尾指针相同
- c. 空队列,头、尾指针相同
由此可见,循环队列不能以头、尾指针的值是否相同来区分队列空间是“满”还是“空”。
解决办法: 少用一个元素空间,即队列空间大小为m时,有m-1个元素就认为是队满。
- d. 当J7,J8,J9入队后,(Q.rear +1)%MAXQSIZE 的值等于Q.front,此时认为队满。
2.结构定义
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int Status;
typedef int QElemType;
typedef struct
{
QElemType data[MAXSIZE];
int front; /* 头指针 */
int rear; /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
}SqQueue;
3.基本实现
Status InitQueue(SqQueue *Q){
Q->front = 0;
Q->rear = 0;
return OK;
}
Status ClearQueue(SqQueue *Q){
Q->front = Q->rear = 0;
return OK;
}
Status QueueEmpty(SqQueue Q){
if (Q.front == Q.rear)
return TRUE;
else
return FALSE;
}
int QueueLength(SqQueue Q){
return (Q.rear - Q.front + MAXSIZE)%MAXSIZE;
}
Status GetHead(SqQueue Q,QElemType *e){
if (Q.front == Q.rear)
return ERROR;
*e = Q.data[Q.front];
return OK;
}
Status EnQueue(SqQueue *Q,QElemType e){
if((Q->rear+1)%MAXSIZE == Q->front)
return ERROR;
Q->data[Q->rear] = e;
Q->rear = (Q->rear+1)%MAXSIZE;
return OK;
}
Status DeQueue(SqQueue *Q,QElemType *e){
if (Q->front == Q->rear) {
return ERROR;
}
*e = Q->data[Q->front];
Q->front = (Q->front+1)%MAXSIZE;
return OK;
}
Status QueueTraverse(SqQueue Q){
int i;
i = Q.front;
while (i != Q.rear) {
printf("%d ",Q.data[i]);
i = (i+1)%MAXSIZE;
}
printf("\n");
return OK;
}
int main(int argc, const char * argv[]) {
Status j;
int i=0;
QElemType d;
SqQueue Q;
InitQueue(&Q);
printf("初始化队列后,队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
printf("入队:\n");
while (i < 10) {
EnQueue(&Q, i);
i++;
}
QueueTraverse(Q);
printf("队列长度为: %d\n",QueueLength(Q));
printf("现在队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
printf("出队:\n");
DeQueue(&Q, &d);
printf("出队的元素:%d\n",d);
EnQueue(&Q, 10);
QueueTraverse(Q);
j=GetHead(Q,&d);
if(j)
printf("现在队头元素为: %d\n",d);
ClearQueue(&Q);
printf("清空队列后, 队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
return 0;
}
三.队列的链式表示和实现
1.结构定义
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int Status;
typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front,rear; /* 队头、队尾指针 */
}LinkQueue;
2.基本操作
Status InitQueue(LinkQueue *Q){
Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));
if (!Q->front) {
return ERROR;
}
Q->front->next = NULL;
return OK;
}
Status DestoryQueue(LinkQueue *Q){
while (Q->front) {
Q->rear = Q->front->next;
free(Q->front);
Q->front = Q->rear;
}
return OK;
}
Status ClearQueue(LinkQueue *Q){
QueuePtr p,q;
Q->rear = Q->front;
p = Q->front->next;
Q->front->next = NULL;
while (p) {
q = p;
p = p->next;
free(q);
}
return OK;
}
Status QueueEmpty(LinkQueue Q){
if (Q.front == Q.rear)
return TRUE;
else
return FALSE;
}
int QueueLength(LinkQueue Q){
int i= 0;
QueuePtr p;
p = Q.front;
while (Q.rear != p) {
i++;
p = p->next;
}
return i;
}
Status EnQueue(LinkQueue *Q,QElemType e){
QueuePtr s = (QueuePtr)malloc(sizeof(QNode));
if (!s) {
return ERROR;
}
s->data = e;
s->next = NULL;
Q->rear->next = s;
Q->rear = s;
return OK;
}
Status DeQueue(LinkQueue *Q,QElemType *e){
QueuePtr p;
if (Q->front == Q->rear) {
return ERROR;
}
p = Q->front->next;
*e = p->data;
Q->front->next = p ->next;
if(Q->rear == p) Q->rear = Q->front;
free(p);
return OK;
}
Status GetHead(LinkQueue Q,QElemType *e){
if (Q.front != Q.rear) {
*e = Q.front->next->data;
return TRUE;
}
return FALSE;
}
Status QueueTraverse(LinkQueue Q){
QueuePtr p;
p = Q.front->next;
while (p) {
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return OK;
}
int main(int argc, const char * argv[]) {
Status iStatus;
QElemType d;
LinkQueue q;
iStatus = InitQueue(&q);
if (iStatus) {
printf("成功地构造了一个空队列\n");
}
printf("是否为空队列?%d (1:是 0:否)\n",QueueEmpty(q));
printf("队列的长度为%d\n",QueueLength(q));
EnQueue(&q, -3);
EnQueue(&q, 6);
EnQueue(&q, 12);
printf("队列的长度为%d\n",QueueLength(q));
printf("是否为空队列?%d (1:是 0:否)\n",QueueEmpty(q));
printf("队列中的元素如下:\n");
QueueTraverse(q);
iStatus = GetHead(q, &d);
if (iStatus == OK) {
printf("队头元素是:%d\n",d);
}
iStatus =DeQueue(&q, &d);
if (iStatus == OK) {
printf("删除了的队头元素为:%d\n",d);
}
iStatus = GetHead(q, &d);
if (iStatus == OK) {
printf("新的队头元素为:%d\n",d);
}
ClearQueue(&q);
DestoryQueue(&q);
return 0;
}