数据结构C语言—线性表【队列】静态顺序队列(定义结构体变量实现)(具有自动调整功能防止假溢出)【2021-11-14】

数据结构C语言—线性表【队列】静态顺序队列(定义结构体变量实现)(具有自动调整功能防止假溢出)


【注1】实现了一个自动调整队列在队列空间分布的函数,解决普通数组的静态队列假溢出状态;
【注2】自动调整函数的被动触发:在入队函数调用时(遇到假溢出先调整再入队)、在出队函数调用时(遇到假溢出先调整再出队);
【注3】自动调整函数的主动执行:手动调用自动调整函数Status AutoMemory_Queue(SqQueuePonit Q)即可。
【注4】由于测试极限与假溢出情况需要,故只将队列空间数组元素个数设置为6(MAXSIZE),使用时可修改该宏定义!

SqQueuestatic.h

#define MAXSIZE 6
#define NOINIT -1 
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE 1
#define OVERFLOW 1

typedef int Status;
typedef int DataType;
typedef int *Pt;
typedef struct SqQueue
{
	DataType rear;//指向队尾元素的下一个顺序位置(以数组元素下表作为指针)
	DataType front;// 指向队头的指针(以数组元素下表作为指针) 
	DataType length;//队列中元素的个数,即队列长度 
	DataType data[MAXSIZE];//队列数组元素个数,为定值分配空间
}SqQueue,*SqQueuePonit;

Status InitQueue(SqQueuePonit Q);//初始化一个空静态顺序队列Q,成功返回OK,否则返回ERROR 
Status ClearQueue(SqQueuePonit Q);//清空静态顺序队列Q,返回OK;静态顺序队列Q未初始化(NOINIT);队尾指针等于队头指针——空状态标志
//Status DestoryQueue(SqQueuePonit Q);//销毁一个队列Q 

Status IsEmptyQueue(SqQueuePonit Q);//判断一个队列是否为空,是空(TRUE),不是空(FALSE);静态顺序队列Q未初始化(NOINIT) 
DataType QueueLength(SqQueuePonit Q);//返回队列Q的元素个数,即队列长度,静态顺序队列Q未初始化(NOINIT)

Status GetTop_Queue(SqQueuePonit Q,Pt e);//若队列不空,用*e返回队列Q头的元素,返回OK;若队列空(ERROR);静态顺序队列Q未初始化(NOINIT)   
Status Push_Queue(SqQueuePonit Q,DataType e);//若队列不满,将e入队列,返回OK;队列满,返回ERROR;静态顺序队列Q未初始化(NOINIT)  
Status Pop_Queue(SqQueuePonit Q,Pt e);//若队列不空,将队列头元素出队列,即删除队列顶元素,用*e返回其值,返回OK;若队列空(ERROR);静态顺序队列Q未初始化(NOINIT)  
Status QueueTraverse(SqQueuePonit Q,Status (*Visit)(SqQueuePonit Q,DataType p));//队列不空,对每个元素调用Visist(),返回OK;若队列空(ERROR);静态顺序队列Q未初始化(NOINIT) 

Status Visit(SqQueuePonit Q,DataType p);//遍历调用函数 

//下面是一个判断当前队列空间是否处于假溢出(假满)状态
Status IsVirFull_Queue(SqQueuePonit Q); 

//下面是一个静态顺序队列空间的自动调整函数,防止假溢出(假满)状态
Status AutoMemory_Queue(SqQueuePonit Q);


SqQueuestatic.c

#include "SqQueuestatic.h" 
#include <stdio.h>

Status InitQueue(SqQueuePonit Q)//初始化一个空静态顺序队列Q,成功返回OK,否则返回ERROR 
{
	puts("\n|<=====================开始【初始化队列】操作!=====================>|");
	Q->front = 0;//默认起始从数组0位置增长队列 
	Q->rear = Q->front;//队列为空标志,队尾指针始终指向实际队尾元素的下一个顺序位置 
	Q->length = 0;//队列长度置为0 
	for(int i = 0;i<MAXSIZE;i++)//给静态数组队列的每个元素赋初始值
	{
		(Q->data)[i]=0;
	}
	puts("|<=====================完成【初始化队列】操作!=====================>|");
	return OK; 
}
Status ClearQueue(SqQueuePonit Q)//清空静态顺序队列Q,返回OK;静态顺序队列Q未初始化(NOINIT);队尾指针等于队头指针——空状态标志
{
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		puts("\n|!===========静态顺序队列【未初始化】不能执行【清空】操作===========!|");
		return  NOINIT;
	}
	puts("\n|<===================开始【清空】静态顺序队列!=====================>|");
	Q->front=Q->rear=0;//空队列状态标志,默认起始从数组0位置增长队列 
	Q->length = 0;//队列长度置为0 
	puts("|<===================【清空】静态顺序队列完成!=====================>|");
	return OK; 	
}
//Status DestoryQueue(SqQueuePonit Q);//销毁一个队列Q 

Status IsEmptyQueue(SqQueuePonit Q)//判断一个队列是否为空,是空(TRUE),不是空(FALSE);静态顺序队列Q未初始化(NOINIT) 
{
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		puts("\n|!===========静态顺序队列【未初始化】不能执行【判空】操作===========!|");
		return  NOINIT;
	}
	if(Q->front==Q->rear)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}	
}
DataType QueueLength(SqQueuePonit Q)//返回队列Q的元素个数,即队列长度,静态顺序队列Q未初始化(NOINIT)
{
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		puts("\n|!===========静态顺序队列【未初始化】不能执行【求长】操作===========!|");
		return  NOINIT;
	}
	return Q->length = Q->rear - Q->front; 	
}

Status GetTop_Queue(SqQueuePonit Q,Pt e)//若队列不空,用*e返回队列Q头的元素,返回OK;若队列空(ERROR);静态顺序队列Q未初始化(NOINIT)   
{
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		*e = -6699;
		puts("\n|!===========静态顺序队列【未初始化】不能执行【获头】操作===========!|");
		return  NOINIT;
	}
	if(IsEmptyQueue(Q) == TRUE)
	{
		*e=-6699;
		puts("\n|!===========静态顺序队列【是空队列】不能执行【获头】操作===========!|");
		return  ERROR;
	}
	else
	{
		*e=Q->data[Q->front];
		printf("当前静态顺序队列Q中,队头元素是:%d\n",*e);
		return OK;
	}
}
Status Push_Queue(SqQueuePonit Q,DataType e)//若队列不满,将e入队列,返回OK;队列满,返回ERROR;静态顺序队列Q未初始化(NOINIT) 
{
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		puts("\n|!===========静态顺序队列【未初始化】不能执行【入队】操作===========!|");
		return  NOINIT;
	}
	//printf("%d,%d\n",QueueLength(Q) == MAXSIZE,Q->rear == MAXSIZE);
	if(QueueLength(Q) == MAXSIZE && Q->rear == MAXSIZE)
	{
		puts("\n|!===========静态顺序队列【队列真满】不能执行【入队】操作===========!|");
		return  ERROR;
	}
	else if(IsVirFull_Queue(Q) == TRUE)
	{
		puts("\n|!===========静态顺序队列【队列假满】开始执行【自调】操作===========!|");
		AutoMemory_Queue(Q);
		puts("\n|!===========静态顺序队列【自动调整】已经执行【完毕】操作===========!|");
		Q->data[(Q->rear)++] = e;
		(Q->length)++;
		puts("\n|-===========静态顺序队列【加入队列】已经执行【完毕】操作===========>|");
		return OK;
	} 
	else
	{
		puts("\n|<===========静态顺序队列【有剩空间】开始执行【入队】操作===========-|");
		Q->data[(Q->rear)++] = e;
		(Q->length)++;
		puts("\n|-===========静态顺序队列【加入队列】已经执行【完毕】操作===========>|");
		return OK;
	}
	return ERROR;
}
Status Pop_Queue(SqQueuePonit Q,Pt e)//若队列不空,将队列头元素出队列,即删除队列顶元素,用*e返回其值,返回OK;若队列空(ERROR);静态顺序队列Q未初始化(NOINIT) 
{
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		*e = -6699;
		puts("\n|!===========静态顺序队列【未初始化】不能执行【出队】操作===========!|");
		return  NOINIT;
	}
	if(IsEmptyQueue(Q) == TRUE)
	{
		*e=-6699;
		puts("\n|!===========静态顺序队列【是空队列】不能执行【出队】操作===========!|");
		return  ERROR;
	}
	else if(IsVirFull_Queue(Q) == TRUE)
	{
		puts("\n|!===========静态顺序队列【队列假满】开始执行【自调】操作===========!|");
		AutoMemory_Queue(Q);
		puts("\n|!===========静态顺序队列【自动调整】已经执行【完毕】操作===========!|");
		puts("\n|!===========静态顺序队列【空间正常】开始执行【出队】操作===========!|");
		*e=(Q->data)[(Q->front)++];
		printf("Q-FRONT:%d",Q->front);
		(Q->length)--;
		puts("\n|!===========静态顺序队列【空间正常】已经执行【完毕】操作===========!|");
		return OK;
	} 
	else
	{
		puts("\n|!===========静态顺序队列【空间正常】开始执行【出队】操作===========!|");
		*e=(Q->data)[(Q->front)++];
		printf("Q-FRONT:%d",Q->front);
		(Q->length)--;
		puts("\n|!===========静态顺序队列【空间正常】已经执行【完毕】操作===========!|");
		return OK;
	}
	return ERROR;
}
Status QueueTraverse(SqQueuePonit Q,Status (*Visit)(SqQueuePonit Q,DataType p))//队列不空,对每个元素调用Visist(),返回OK;若队列空(ERROR);静态顺序队列Q未初始化(NOINIT) 
{
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		puts("\n|!===========静态顺序队列【未初始化】不能执行【遍历】操作===========!|");
		return  NOINIT;
	}
	if(IsEmptyQueue(Q) == TRUE)
	{
		puts("\n|<=====================开始【全遍历队列】操作!=====================>|");
		printf("队头指针----->%d:空<-----队尾巴指针\n",Q->front); 
		puts("|<=====================完成【全遍历队列】操作!=====================>|");
		return ERROR;
	} 
	else
	{
		puts("\n|<=====================开始【全遍历队列】操作!=====================>|");
		DataType p;
		printf("队尾指针----->%d\n",Q->rear); 
		for(p = Q->rear-1;p != Q->front - 1;p--)
		{
//			printf("p=%d\n",p);
			Visit(Q,p);
		}
		puts("|<=====================完成【全遍历队列】操作!=====================>|");
		return OK;
	}	
}

Status Visit(SqQueuePonit Q,DataType p)//遍历调用函数
{
	if(p == Q->front)
	{
		printf("队头指针----->%d:%d\n",p,(Q->data)[p]);
	}
	else
	{
		printf("              %d:%d\n",p,(Q->data)[p]);
	}
	return OK;	
}

//下面是一个判断当前队列空间是否处于假溢出(假满)状态
Status IsVirFull_Queue(SqQueuePonit Q)
{
	//只要rear指针指向数组MAXSIZE位置且队列长度小于队列空间数组长度,就视为处于假溢出状态 
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		puts("\n|!===========静态顺序队列【未初始化】不能执行【判假】操作===========!|");
		return  NOINIT;
	}
	if(Q->rear == MAXSIZE && QueueLength(Q) < MAXSIZE)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

//下面是一个静态顺序队列空间的自动调整函数,防止假溢出(假满)状态
Status AutoMemory_Queue(SqQueuePonit Q)
{
	//自动调整操作可以在任意已经初始化状态后使用 
	//将处于假溢出状态的整个队列的front对齐到数组0位置,即将整个队列在数组空间中下拉
	int i;
	int t = Q->front;
	if(Q->front >= MAXSIZE || Q->front < 0 || Q->rear > MAXSIZE || Q->rear < 0 || Q->front > Q->rear)
	{
		puts("\n|!===========静态顺序队列【未初始化】不能执行【自调】操作===========!|");
		return  NOINIT;
	} 
	puts("\n###@@!===========静态顺序队列【开始】【自动调整】操作===========!@@###");
	for(i = 0;i < MAXSIZE;i++,t++)
	{
		if(t == Q->rear)
		{
			break;
		}
		else
		{
			Q->data[i] = Q->data[t];
		}
	}
	Q->front = 0;
	Q->rear = i;
	puts("###@@!===========静态顺序队列【完成】【自动调整】操作===========!@@###");
	return OK;
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "SqQueuestatic.h" 
/* 线性表——顺序队列(静态分配)【自编代码】 */ 
int main() 
{
	SqQueue Q;
	int e;
	
	GetTop_Queue(&Q,&e); 
	ClearQueue(&Q);
	AutoMemory_Queue(&Q);
	if(IsEmptyQueue(&Q) == TRUE)
	{
		printf("Q是空队列!\n");
	}
	else if(IsEmptyQueue(&Q) == FALSE) 
	{
		printf("Q不是空队列!\n");
	}
	QueueLength(&Q);
	Push_Queue(&Q,888);
	Pop_Queue(&Q,&e);
	QueueTraverse(&Q,Visit); 
	
	puts("\n为了方便测试极限情况与队列假溢出状态,设置队列空间数组元素个数为6(MAXSIZE)!");
	InitQueue(&Q);

	GetTop_Queue(&Q,&e); 
	AutoMemory_Queue(&Q);
	if(IsEmptyQueue(&Q) == TRUE)
	{
		printf("Q是空队列!\n");
	}
	else if(IsEmptyQueue(&Q) == FALSE) 
	{
		printf("Q不是空队列!\n");
	}
	printf("Q长度是:%d\n",QueueLength(&Q));
	Push_Queue(&Q,888);
	Pop_Queue(&Q,&e);
	QueueTraverse(&Q,Visit); 
	ClearQueue(&Q);
	
	
	puts("请按先后顺序,输入要入队的元素(空格分隔,f结束):");
	while(1)
	{
		int n,k;
		k=scanf("%d",&n);
		if(k==0)
		{
			break;
		}
		Push_Queue(&Q,n);
	}
	QueueTraverse(&Q,Visit); 
	GetTop_Queue(&Q,&e); 


	puts("测试再入队一个元素999:\n");
	Push_Queue(&Q,999);
	QueueTraverse(&Q,Visit); 
	printf("Q长度:%d\n",QueueLength(&Q));
	
	puts("测试再入队一个元素666:\n");
	Push_Queue(&Q,666);
	QueueTraverse(&Q,Visit); 
	printf("Q长度是:%d\n",QueueLength(&Q));
	GetTop_Queue(&Q,&e); 
	
	puts("测试执行出队一个元素:\n");
	Pop_Queue(&Q,&e);
	QueueTraverse(&Q,Visit); 
	printf("Q长度是:%d\n",QueueLength(&Q));
	
	puts("测试执行出队一个元素:\n");
	Pop_Queue(&Q,&e);
	QueueTraverse(&Q,Visit); 
	QueueTraverse(&Q,Visit); 
	GetTop_Queue(&Q,&e); 
	
	puts("测试再入队一个元素777:\n");
	Push_Queue(&Q,777);
	QueueTraverse(&Q,Visit); 
	
	puts("测试执行出队一个元素:\n");
	Pop_Queue(&Q,&e);
	QueueTraverse(&Q,Visit); 
	GetTop_Queue(&Q,&e); 
	
	puts("测试执行出队一个元素:\n");
	Pop_Queue(&Q,&e);
	QueueTraverse(&Q,Visit); 
	GetTop_Queue(&Q,&e); 
	
	puts("\n手动调用一次自调操作:"); 
	AutoMemory_Queue(&Q);
	QueueTraverse(&Q,Visit); 
	printf("Q长度是:%d\n",QueueLength(&Q));
	
	ClearQueue(&Q);
	QueueTraverse(&Q,Visit); 
	
	return 0;
}

运行结果示例

由于程序运行测试输出过多,因此分段截图,按顺序放置:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


------------------------------------------------------第八次发文章有点激动啊!-----------------------------------------------------
-----------------------------------------------------【数据结构代码自编练习】------------------------------------------------------
----------------------------------------------------------------【TDTX】-----------------------------------------------------------------

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值