// c3-4.h 队列的顺序存储结构(出队元素时不移动元素,只改变队头元素的位置)
#define QUEUE_INIT_SIZE 10 // 队列存储空间的初始分配量
#define QUEUE_INCREMENT 2 // 队列存储空间的分配增量
struct SqQueue2//(见图3.25)
{
QElemType *base; // 初始化的动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
int queuesize; // 当前分配的存储容量(以sizeof(QElemType)为单位)
};
图326 是根据c3-4.h 定义的有3 个元素的非循环队列。bo3-4.cpp 和bo3-9.cpp 是
这种结构的基本操作。因为后面的程序还要调用bo3-4.cpp,所以将9 个基本操作分别放
在两个文件中。
// bo3-4.cpp 顺序队列(存储结构由c3-4.h定义)的基本操作(5个)
void InitQueue(SqQueue2 &Q)
{ // 构造一个空队列Q(见图3.27)
if(!(Q.base=(QElemType *)malloc(QUEUE_INIT_SIZE*sizeof(QElemType)))) // 存储分配失败
exit(ERROR);
Q.front=Q.rear=0;
Q.queuesize=QUEUE_INIT_SIZE;
}
void DestroyQueue(SqQueue2 &Q)
{ // 销毁队列Q,Q不再存在(见图3.28)
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的新的队尾元素(见图3.29)
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(见图3.30)
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.cpp 顺序队列(非循环),检验bo3-4.cpp和bo3-9.cpp的主程序
#include"c1.h"
typedef int QElemType;
#include"c3-4.h"
#include"bo3-4.cpp" // 基本操作(1)
//#include"bo3-9.cpp" // 基本操作(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);
}
/*
初始化队列后,队列空否?1(1:空0:否)
队列长度为0
请输入11个整型队列元素:
0 1 2 3 4 5 6 7 8 9 10
队列长度为11
现在队列空否?0(1:空0:否)
现在队列中的元素为
0 1 2 3 4 5 6 7 8 9 10
删除队头元素0
队列中的元素为
1 2 3 4 5 6 7 8 9 10
队头元素为1
清空队列后, 队列空否?1(1:空0:否)
无队头元素(空队列)
*/
c3-4.h 定义的队列顺序存储结构,在出队元素时,只是改变头指针的位置,不移动元
素,可简化操作,节约时间,这从DeQueue()函数和图330 可看出。但这种队列顺序存
储结构也有它的缺点,队列的每个存储空间自始至终只能存一个队列元素。即使这个队列
元素出队后,其它的队列元素也不能占用这个存储空间。尤其在队列长度不长,入队出队
频繁的情况下,存储空间浪费较大。由于没有其它数据覆盖,当队头元素出队后,其值还
保留在队列中。后面的algo3-11.cpp(另一种求迷宫方法)就利用了c3-4.h 的这个特点。