概述
和栈相反,队列(queue)是一种先进先出(first in first out,缩写FIFO)的线性表。它只允许在表的一端进行插入,而在另一端删除元素。
1、抽象数据类型定义
基本操作
InitQueue(&Q)
操作结果:构建一个空队列Q
DestroyQueue(&Q)
操作结果:队列Q被销毁,不再存在
ClearQueue(&Q)
操作结果:将队列Q清空
QueueIsEmpty(Q)
操作结果:判断队列是否为空
QueueLength(Q)
操作结果:返回Q的元素个数,即队列长度
QueueHead(Q)
操作结果:用e返回队列Q的头元素
EnQueue(&Q, e)
操作结果:出入元素e为队列Q的新的队尾元素
DeQueue(&Q, &e)
操作结果:删除Q的队头元素,并用e返回其值
QueueTraverse(Q, visit())
操作结果:从队头到队尾,依次对Q的每个数据元素调用函数visit()。一旦visit()失败,则操作失败
2、循环队列
从上图3.13可看出,在C语言中不能用动态分配的一维数组来实现循环链表。如果用户的应用程序中设有循环队列,则必须为它设定一个最大队列长度;若用户无法预估所用队列的最大长度,则以采用链队列。
队列的顺序存储结构
#define MAXQSIZE 100 //最大队列长度
typedef struct
{
QElemType *base;
int front; //队首指针
int rear; //队尾指针
}SqQueue;
基本操作算法
Status InitQueue(SqQueue &Q)
{
Q.base = (QElemType*)malloc(MAXQSIZE * sizeof(QElemType));
if(!Q.base) exit(OVERFLOW);
Q.rear = 0;
Q.front = 0;
return OK;
}
int isEmpty(SqQueue Q)
{
return (Q.front == Q.rear ? 1 : 0);
}
int QueueLength(SqQueue Q)
{
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
Status EnQueue(SqQueue &Q, QElemType e)
{
if((Q.rear+1)%MAXQSIZE== Q.front)
{
return ERROR;
}
Q.base[Q.rear] = e;
Q.rear = (Q.rearr+1)%MAXQSIZE;
return OK;
}
Status DeQueue(SqQueue &Q, QElemType &e)
{
if(Q.rear == Q.front)
{
return ERROR;
}
e = Q.base[Q.front];
Q.front = (Q.front+1)%MAXQSIZE;
return OK;
}
3、链队列
#include "stdio.h"
#define QueueSize 100 /*假定预分配的队列空间最多为100个元素*/
typedef char DataType ; /*假定队列元素的数据类型为字符*/
typedef struct node{
DataType data;
struct node *next;
}QueueNode;
typedef struct{
QueueNode *front; /*头指针*/
QueueNode *rear;
}LinkQueue;
/* 置队列空*/
void Initial(LinkQueue *Q)
{
Q->front=Q->rear=NULL;/*将顺序队列置空*/
}
/*判队列空*/
int IsEmpty(LinkQueue *Q)
{
return Q->front==NULL&&Q->rear==NULL;
}
/*进队列*/
void Push(LinkQueue *Q,DataType x)
{
/*将元素x插入链队列尾部*/
QueueNode *p=(QueueNode *)malloc(sizeof(QueueNode));/*申请新结点*/
p->data=x;
p->next=NULL;
if(IsEmpty(Q))
Q->front=Q->rear=p; /*将x插入空队列*/
else
{ /*x插入非空队列的尾*/
Q->rear->next=p; /*p链到原队尾结点后*/
Q->rear=p; /*队尾指针指向新的尾*/
}
}
/*出队列*/
DataType Pop(LinkQueue *Q)
{
DataType x;
QueueNode *p;
if(IsEmpty(Q))
{
printf("队列为空");/*下溢*/
exit(1);
}
p=Q->front; /*指向对头结点*/
x=p->data; /*保存对头结点的数据*/
Q->front=p->next; /*将对头结点从链上摘下*/
if(Q->rear==p)/*原队中只有一个结点,删去后队列变空,此时队头指针已为空*/
Q->rear=NULL;
free(p); /*释放被删队头结点*/
return x; /*返回原队头数据*/
}
/* 取队列顶元素*/
DataType Front(LinkQueue *Q)
{
if(IsEmpty(Q))
{
printf("队列为空"); /*下溢,退出运行*/
exit(1);
}
return Q->front->data;
}
void main()
{
LinkQueue s;
DataType first,sec;
Initial(&s);
Push(&s,'a');
Push(&s,'b');
first=Front(&s);
Pop(&s);
sec=Front(&s);
Pop(&s);
}