/*顺序队列的类型定义*/
#define MAXQSIZE 100 /*最大队列长度*/
#define OK 1;
#define ERROR 0;
typedef struct{
int *base; /*初始化的动态分配存储空间*/
int front; /*头指针*/
int rear; /*尾指针*/}SqQueue;
创建空队列时,令front=rear=0,每当插入新的队尾元素时,尾指针rear增1,每当删除队头元素时,头指针front增1。因此,在非空队列中,头指针始终指向队列头元素,
而尾指针始终指向队尾元素的下一个位置。
这样会造成"假溢出",这是由“队尾入队,队头出队”,这种受限制的操作造成的,解决方法是构造循环队列。
对于循环队列不能以头、尾指针的值是否相同来判别队列空间是“满”还是“空”,因为队空和队满都是Q.front=Q.rear,那该如何区别队满还是队空?
1)少用一个元素空间,即队列空间大小为m时,有m-1个元素就任务是队满。这样判断队空的条件不变,即当头、尾指针的值相同时就认为队空;
而当尾指针在循环意义上加1后等于头指针,则认为队满。因此
队空的条件:Q.front == Q.rear
队满的条件: (Q.rear+1)%MAXQSIZE == Q.front
2)另设一个标志位以区别队列是“空”还是“满”。
[代码实现]
1.初始化
int InitQueue(SqQueue &Q)
{
/*构造一个空队列Q*/
Q.base= new int[MAXQSIZE];
if(!Q.base) exit(OVERFLOW);
Q.front=Q.rear=0;
return OK;
}
2.求队列长度
int QueueLength(SqQueue Q)
{
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}
3.入队int EnQueue(SqQueue &Q,int e)
{
/*插入元素e为Q的新队尾元素*/
if((Q.rear+1)%MAXQSIZE == Q.front) /*尾指针在循环意义上加1等于头指针,表明队满*/
return ERROR;
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%MAXQSIZE;
return OK;
}
4.出队int DeQueue(SqQueue &Q,int &e)
{
/*若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR*/
if(Q.front==Q.rear) return ERROR;
e=Q.base[Q.front];
Q.front=(Q.front+1)%MAXQSIZE;
return OK;
}
二、链队—队列的链式表示和实现
/*链队类型的定义*/
typedef struct QNode
{
int data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front; /*队头指针*/
QueuePtr rear; /*队尾指针*/
}LinkQueue;
[代码实现]
int InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=new QNode;
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
2.入队int EnQueue(LinkQueue &Q,int e)
{
p=new QNode;
if(!p) exit(OVERFLOW);
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p; /*修改队尾指针*/
return OK;
}
3.出队int DeQueue(LinkQueue &Q,int &e)
{
/*删除Q的队头元素,用e返回其值,并返回OK*/
if(Q.front==Q.rear) return ERROR;
p=Q.front->next; /*p指向队头元素*/
e=p->data;
Q.front->next=p->next; /*修改头指针*/
if(Q.rear==p) Q.rear=Q.front; /*最后一个元素被删,队尾指针指向头结点*/
delete p;
return OK;
}