两种非循环顺序队列的表示和实现(第三章)

两种非循环顺序队列的表示和实现

第一种:

存储空间可增,队头元素总在 [0] 单元,所以不必设头指针。它的缺点是元素出队时需要移动大量元素,尤其在队列较长时,效率较低。


typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int QElemType; /* 定义队列元素的类型 */

#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */

/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2 


/* --------------------------   队列的顺序存储结构  -----------------------------*/

#define QUEUE_INIT_SIZE 10 // 队列存储空间的初始分配量
#define QUEUE_INCREMENT 2 // 队列存储空间的分配增量
typedef struct
{
	QElemType *base; // 初始化的动态分配存储空间
	int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
	int queuesize; // 当前分配的存储容量(以sizeof(QElemType)为单位)
}SqQueue1;

/* ----------------------------------------------------------------------------*/

void print(QElemType i)
{
	printf("%d ", i);
}

/*  顺序非循环队列的基本操作(9个)  */

/* --------------------        基本操作的函数原型说明     ---------------------*/

void InitQueue(SqQueue1 *Q);
void DestroyQueue(SqQueue1 *Q);
void ClearQueue(SqQueue1 *Q);
Status QueueEmpty(SqQueue1 Q);
int QueueLength(SqQueue1 Q);
Status GetHead(SqQueue1 Q, QElemType *e);
void EnQueue(SqQueue1 *Q, QElemType e);
Status DeQueue(SqQueue1 *Q, QElemType *e);
void QueueTraverse(SqQueue1 Q, void(*vi)(QElemType));


/* ---------------------------------             基本操作的实现         ------------------------------------*/


void InitQueue(SqQueue1 *Q)
{ // 构造一个空队列Q(见图321)
	if (!((*Q).base = (QElemType*)malloc
	(QUEUE_INIT_SIZE * sizeof(QElemType))))
		exit(ERROR); // 存储分配失败
	(*Q).rear = 0; // 空队列,尾指针为0
	(*Q).queuesize = QUEUE_INIT_SIZE; // 初始存储容量
}

void DestroyQueue(SqQueue1 *Q)
{ // 销毁队列Q,Q不再存在(见图322)
	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的新的队尾元素(见图323)
	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(见图324)
	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");
}






/*  检验以上操作的主程序 */

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);
}

运行结果:

第二种:

在元素出队时,只是改变头指针的位置,不移动元素,可节约时间。但这种队列即使在元素出队后,其他元素也不能占用这个存储空间,存储空间浪费较大。


typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int QElemType; /* 定义队列元素的类型 */

#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */

/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2 


/* --------------------------   队列的顺序存储结构  -----------------------------*/

#define QUEUE_INIT_SIZE 5 // 队列存储空间的初始分配量
#define QUEUE_INCREMENT 2 // 队列存储空间的分配增量
typedef struct 
{
	QElemType *base; // 初始化的动态分配存储空间
	int front; // 头指针,若队列不空,指向队列头元素
	int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
	int queuesize; // 当前分配的存储容量(以sizeof(QElemType)为单位)
}SqQueue2;

/* ----------------------------------------------------------------------------*/


void print(QElemType i)
{
	printf("%d ", i);
}



/*  循环队列的基本操作(9个) */

/* --------------------        基本操作的函数原型说明     ---------------------*/

void InitQueue(SqQueue2 *Q);
void DestroyQueue(SqQueue2 *Q);
void ClearQueue(SqQueue2 *Q);
Status QueueEmpty(SqQueue2 Q);
Status GetHead(SqQueue2 Q, QElemType *e);
int QueueLength(SqQueue2 Q);
void EnQueue(SqQueue2 *Q, QElemType e);
Status DeQueue(SqQueue2 *Q, QElemType *e);
void QueueTraverse(SqQueue2 Q, void(*vi)(QElemType));



/* ---------------------------------             基本操作的实现         ------------------------------------*/


void InitQueue(SqQueue2 *Q)
{ // 构造一个空队列Q(见图327)
	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不再存在(见图328)
	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;
}

int QueueLength(SqQueue2 Q)
{ // 返回Q的元素个数,即队列的长度
	return(Q.rear - Q.front);
}

void EnQueue(SqQueue2 *Q, QElemType e)
{ // 插入元素e为Q的新的队尾元素(见图329)
	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(见图330)
	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");
}





/*  检验以上操作的主程序 */

void main()
{
	Status j;
	int i, n = 6;
	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_s("%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);
}

运行结果:

发布了135 篇原创文章 · 获赞 64 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_42185999/article/details/104996424
今日推荐