// 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(" "); }
// 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:否) ",QueueEmpty(Q)); printf("队列长度为%d ",QueueLength(Q)); printf("请输入%d个整型队列元素: ",n); for(i=0;i<n;i++) { scanf("%d",&d); EnQueue(Q,d); } printf("队列长度为%d ",QueueLength(Q)); printf("现在队列空否?%u(1:空0:否) ",QueueEmpty(Q)); printf("现在队列中的元素为 "); QueueTraverse(Q,print); DeQueue(Q,d); printf("删除队头元素%d ",d); printf("队列中的元素为 "); QueueTraverse(Q,print); j=GetHead(Q,d); if(j) printf("队头元素为%d ",d); else printf("无队头元素(空队列) "); ClearQueue(Q); printf("清空队列后, 队列空否?%u(1:空0:否) ",QueueEmpty(Q)); j=GetHead(Q,d); if(j) printf("队头元素为%d ",d); else printf("无队头元素(空队列) "); 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 的这个特点。