队列的顺序表示为什么要采用循环方式呢?首先分析非循环顺序队列的表示和实现以及他们存在的问题。
/* c3-5.h 队列的顺序存储结构(非循环队列,队列头元素在[0]单元) */
#define QUEUE_INIT_SIZE 10 /* 队列存储空间的初始分配量 */
#define QUEUE_INCREMENT 2 /* 队列存储空间的分配增量 */
typedef struct
{
QElemType *base; /* 初始化的动态分配存储空间 */
int rear; /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
int queuesize; /* 当前分配的存储容量(以sizeof(QElemType)为单位) */
}SqQueue1;
/* bo3-7.c 顺序非循环队列(存储结构由c3-5.h定义)的基本操作(9个) */
void InitQueue(SqQueue1 *Q)
{ /* 构造一个空队列Q */
(*Q).base=(QElemType*)malloc(QUEUE_INIT_SIZE*sizeof(QElemType));
if(!(*Q).base)
exit(ERROR); /* 存储分配失败 */
(*Q).rear=0; /* 空队列,尾指针为0 */
(*Q).queuesize=QUEUE_INIT_SIZE; /* 初始存储容量 */
}
void DestroyQueue(SqQueue1 *Q)
{ /* 销毁队列Q,Q不再存在 */
free((*Q).base); /* 释放存储空间 */
(*Q).base=NULL;
(*Q).rear=(*Q).queuesize=0;
}
void ClearQueue(SqQueue1 *Q)
{ /* 将Q清为空队列 */
(*Q).rear=0;
}
Status QueueEmpty(SqQueue1 Q)
{ /* 若队列Q为空队列,则返回TRUE;否则返回FALSE */
if(Q.rear==0)
return TRUE;
else
return FALSE;
}
int QueueLength(SqQueue1 Q)
{ /* 返回Q的元素个数,即队列的长度 */
return Q.rear;
}
Status GetHead(SqQueue1 Q,QElemType *e)
{ /* 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR */
if(Q.rear)
{
*e=*Q.base;
return OK;
}
else
return ERROR;
}
void EnQueue(SqQueue1 *Q,QElemType e)
{ /* 插入元素e为Q的新的队尾元素 */
if((*Q).rear==(*Q).queuesize) /* 当前存储空间已满 */
{ /* 增加分配 */
(*Q).base=(QElemType*)realloc((*Q).base,((*Q).queuesize+QUEUE_INCREMENT)*sizeof(QElemType));
if(!(*Q).base) /* 分配失败 */
exit(ERROR);
(*Q).queuesize+=QUEUE_INCREMENT; /* 增加存储容量 */
}
(*Q).base[(*Q).rear++]=e; /* 入队新元素,队尾指针+1 */
}
Status DeQueue(SqQueue1 *Q,QElemType *e)
{ /* 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR */
int i;
if((*Q).rear) /* 队列不空 */
{
*e=*(*Q).base;
for(i=1;i<(*Q).rear;i++)
(*Q).base[i-1]=(*Q).base[i]; /* 依次前移队列元素 */
(*Q).rear--; /* 尾指针前移 */
return OK;
}
else
return ERROR;
}
void QueueTraverse(SqQueue1 Q,void(*vi)(QElemType))
{ /* 从队头到队尾依次对队列Q中每个元素调用函数vi() */
int i;
for(i=0;i<Q.rear;i++)
vi(Q.base[i]);
printf("\n");
}
/* main3-7.c 检验bo3-7.cpp的主程序 */
#include"c1.h"
typedef int QElemType;
#include"c3-5.h"
#include"bo3-7.c"
void print(QElemType i)
{
printf("%d ",i);
}
void main()
{
Status j;
int i,k=5;
QElemType d;
SqQueue1 Q;
InitQueue(&Q);
printf("初始化队列后,队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
for(i=1;i<=k;i++)
EnQueue(&Q,i); /* 依次入队k个元素 */
printf("依次入队%d个元素后,队列中的元素为: ",k);
QueueTraverse(Q,print);
printf("队列长度为%d,队列空否?%u(1:空 0:否)\n",QueueLength(Q),QueueEmpty(Q));
DeQueue(&Q,&d);
printf("出队一个元素,其值是%d\n",d);
j=GetHead(Q,&d);
if(j)
printf("现在队头元素是%d\n",d);
ClearQueue(&Q);
printf("清空队列后, 队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
DestroyQueue(&Q);
}
/* c3-4.h 队列的顺序存储结构(出队元素时不移动元素,只改变队头元素的位置) */
#define QUEUE_INIT_SIZE 10 /* 队列存储空间的初始分配量 */
#define QUEUE_INCREMENT 2 /* 队列存储空间的分配增量 */
typedef struct
{
QElemType *base; /* 初始化的动态分配存储空间 */
int front; /* 头指针,若队列不空,指向队列头元素 */
int rear; /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
int queuesize; /* 当前分配的存储容量(以sizeof(QElemType)为单位) */
}SqQueue2;
/* bo3-4.cpp 顺序队列(存储结构由c3-4.h定义)的基本操作(5个) */
void InitQueue(SqQueue2 *Q)
{ /* 构造一个空队列Q */
(*Q).base=(QElemType *)malloc(QUEUE_INIT_SIZE*sizeof(QElemType));
if(!(*Q).base) /* 存储分配失败 */
exit(ERROR);
(*Q).front=(*Q).rear=0;
(*Q).queuesize=QUEUE_INIT_SIZE;
}
void DestroyQueue(SqQueue2 *Q)
{ /* 销毁队列Q,Q不再存在 */
if((*Q).base)
free((*Q).base);
(*Q).base=NULL;
(*Q).front=(*Q).rear=(*Q).queuesize=0;
}
void ClearQueue(SqQueue2 *Q)
{ /* 将Q清为空队列 */
(*Q).front=(*Q).rear=0;
}
Status QueueEmpty(SqQueue2 Q)
{ /* 若队列Q为空队列,则返回TRUE;否则返回FALSE */
if(Q.front==Q.rear) /* 队列空的标志 */
return TRUE;
else
return FALSE;
}
Status GetHead(SqQueue2 Q,QElemType *e)
{ /* 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR */
if(Q.front==Q.rear) /* 队列空 */
return ERROR;
*e=Q.base[Q.front];
return OK;
}
/* bo3-9.cpp 顺序非循环队列(存储结构由c3-4.h定义)的基本操作(4个) */
int QueueLength(SqQueue2 Q)
{ /* 返回Q的元素个数,即队列的长度 */
return(Q.rear-Q.front);
}
void EnQueue(SqQueue2 *Q,QElemType e)
{ /* 插入元素e为Q的新的队尾元素 */
if((*Q).rear==(*Q).queuesize)
{ /* 队列满,增加存储单元 */
(*Q).base=(QElemType *)realloc((*Q).base,((*Q).queuesize+QUEUE_INCREMENT)*sizeof(QElemType));
if(!(*Q).base) /* 增加单元失败 */
exit(ERROR);
}
(*Q).base[(*Q).rear++]=e;
}
Status DeQueue(SqQueue2 *Q,QElemType *e)
{ /* 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR */
if((*Q).front==(*Q).rear) /* 队列空 */
return ERROR;
*e=(*Q).base[(*Q).front++];
return OK;
}
void QueueTraverse(SqQueue2 Q,void(*vi)(QElemType))
{ /* 从队头到队尾依次对队列Q中每个元素调用函数vi() */
int i=Q.front;
while(i!=Q.rear)
vi(Q.base[i++]);
printf("\n");
}
/* main3-4.c 顺序队列(非循环),检验bo3-4.c和bo3-9.c的主程序 */
#include"c1.h"
typedef int QElemType;
#include"c3-4.h"
#include"bo3-4.c" /* 基本操作(1) */
#include"bo3-9.c" /* 基本操作(2) */
void print(QElemType i)
{
printf("%d ",i);
}
void main()
{
Status j;
int i,n=11;
QElemType d;
SqQueue2 Q;
InitQueue(&Q);
printf("初始化队列后,队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
printf("队列长度为:%d\n",QueueLength(Q));
printf("请输入%d个整型队列元素:\n",n);
for(i=0;i<n;i++)
{
scanf("%d",&d);
EnQueue(&Q,d);
}
printf("队列长度为:%d\n",QueueLength(Q));
printf("现在队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
printf("现在队列中的元素为: \n");
QueueTraverse(Q,print);
DeQueue(&Q,&d);
printf("删除队头元素%d\n",d);
printf("队列中的元素为: \n");
QueueTraverse(Q,print);
j=GetHead(Q,&d);
if(j)
printf("队头元素为: %d\n",d);
else
printf("无队头元素(空队列)\n");
ClearQueue(&Q);
printf("清空队列后, 队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
j=GetHead(Q,&d);
if(j)
printf("队头元素为: %d\n",d);
else
printf("无队头元素(空队列)\n");
DestroyQueue(&Q);
}