队列的顺序存储结构(出队元素时不移动元素,只改变队头元素的位置)

// 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 的这个特点。

posted @ 2014-08-17 21:43  meiyouor  阅读(485)  评论(0编辑  收藏  举报