队列的顺序存储结构

队列的顺序存储结构:要预先分配内存,知道队列的最大长度。

初始化队列时Q.rear=Q.front=0;

队列的顺序存储结构_第1张图片

对尾插入队列元素rear+1,对头删除队列元素front+1,假设当前为队列分配的最大空间为6,则当队列处于图(d)时,再插入元素会溢出队列,然而此时又不宜像顺序栈那样,进行存储再分配扩大数组空间,但是实则队列的实际可用空间并未占满。于是可以假象构造成环状的空间。

队列的顺序存储结构_第2张图片

但此时Q.rear=Q,front并不能确定是空队列还是满队列,可用两种方法处理: 第一种是设置一个标志位以区分队列是空还是满   ;第二种是少用一个元素空间,约定以 对头指针在队尾指针的下一个位置上时队列为满队列。

队列的顺序存储结构_第3张图片

C实现循环队列如下:

#include 
#ifndef STATUS_H
#define STATUS_H

/* 状态码 */
#define	TRUE		1			//真 
#define	FALSE		0			//假
#define YES			1			//是
#define NO          0			//否 
#define	OK			1			//通过
#define	ERROR		0			//错误
#define SUCCESS		1			//成功 
#define UNSUCCESS	0			//失败 
#define	INFEASIBLE	-1			//不可行

#ifndef _MATH_H_ 				//系统中已有此状态码定义,要避免冲突 
#define	OVERFLOW	-2			//堆栈上溢
#define UNDERFLOW	-3			//堆栈下溢
#endif 

#ifndef NULL
#define NULL ((void*)0)
#endif

/* 状态码识别类型 */
typedef int Status;


//循环队列-----队列的顺序存储结构
//----顺序存储结构,事先知道队列的最大长度 
typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为char */
#define MAXQSIZE 100  //最大队列长度 
typedef struct{ 
	QElemType *base;/* 初始化的动态分配存储空间 */
	int front; //头指针,若队列不为空,指向队列头元素 
	int rear; //尾指针,若队列部位空,指向对尾的元素的下一个位置 
}SeQueue;

//基本操作的函数原型说明
//构造一个空队列 
void InitQueue(SeQueue *Q); 

//销毁队列,Q不存在 
Status DestoryQueue(SeQueue *Q);

//将Q清为空队列
Status ClearQueue(SeQueue *Q);

//若Q为空队列,则返回TURE,否则返回FALSE
Status EmptyQueue(SeQueue Q);

//若Q为满队列,则返回TRUE,否则返回FALSE-
Status FullQueue(SeQueue Q); 

//队列长度
int QueueLength(SeQueue Q);

//队列不为空,用e返回队列的头元素,并返回OK,否则返回ERROR
Status GetHead(SeQueue Q, QElemType *e);

//掺入元素e为Q的新对尾元素
Status EnQueue(SeQueue *Q, QElemType e);

//队列不为空时,删除Q的队列头元素,用e返回其值,并返回OK, 否则返回ERROR
Status DeQueue(SeQueue *Q, QElemType *e);

//从对头到对尾依次调用visit函数,失败的话,则操作失败。 
Status QueueTraverse(SeQueue Q, Status(*Visit)()); 

//方法
//构造一个空队列Q 
void InitQueue(SeQueue *Q){
	//base指针用于申请指针并存放数据
	Q->base= (QElemType*)malloc(MAXQSIZE*sizeof(QElemType));  
	if(!Q->base){
 		exit(OVERFLOW);
	}
	Q->front=Q->rear=0;//队列为空 
	return OK;
}

//判断队列是否为空或为满---预留一位来判断是否为空还是满对 
//初始化时,front=rear=0为空,rear=(0+1)%100=1,队列未满
//队列为满时,rear=(99+1)%100=0,此时队列为满队列,不能插入数据 
Status EmptyQueue(SeQueue Q){
	if(Q.front==Q.rear)
		return TRUE;
	else
		return FALSE;
}

//判断队列是否为满队列
//预留一位来判断,(rear+1)%MAXSIZE=0为满队 
Status FullQueue(SeQueue Q){
	if((Q.rear+1)%MAXQSIZE == 0)
		return TRUE;
	else
		return FALSE;
} 
//在对尾插入元素e,若为满队列时溢出 
Status EnQueue(SeQueue *Q, QElemType e){
	if(FullQueue(*Q))
		return ERROR;
	Q->base[Q->rear] = e;
	Q->rear++;
	return OK; 
}	

//求队列长度 
int QueueLength(SeQueue Q){
	return Q.rear-Q.front;
}
//打印队列元素 
Status QueueTraverse(SeQueue Q, Status(*Visit)()){
	int e;
	int i=0;
	for (i=Q.front; ibase[Q->front];
	Q->front++;
	return OK;
}
//获取对头元素
Status GetHead(SeQueue Q, QElemType *e){
	if (EmptyQueue(Q)){
		return ERROR; 
	}
	*e = Q.base[Q.front];
	return OK;
} 
//清空队列
Status ClearQueue(SeQueue *Q){
	if (EmptyQueue(*Q)){
		return OK; 
	}
	Q->front=Q->rear=0;
	return OK;
} 
//销毁队列--释放队列内存 
Status DestoryQueue(SeQueue *Q){
	free(Q->base);
	Q->base=NULL;
	Q->front=Q->rear=0;
	return OK;
}

//主函数
void PrintElem(QElemType e);
int main(int argc, char **argv){
	SeQueue Q;  
	int i = 0;
	QElemType e; 
	//初始化队列 
	
	printf("初始化循环队列Q...\n\n");	
	InitQueue(&Q);
	
	//判断队列是否为空
	EmptyQueue(Q) ? printf("队列为空!!\n\n") : printf("队列不为空!\n\n");
	
	//往队列插入0-9个数---为Q的新的队尾元素 
	for (i=0; i<=98; i++){
		EnQueue(&Q, i);
	}
	
	//判断队列是否为空
	EmptyQueue(Q) ? printf("队列为空!!\n\n") : printf("队列不为空!\n\n");
	
	//队列长度
	printf("队列长度%d\n\n", QueueLength(Q)); 
	
	//打印数列
	printf("打印队列元素:"); 
	QueueTraverse(Q, PrintElem); 
	printf("\n\n");
	
	//打印队列长度
	printf("队列长队为%d\n\n", QueueLength(Q)); 
	
	//删除对头元素,用e返回
	DeQueue(&Q, &e); 
	printf("删除的对头元素为%d\n\n", e);
	
	//printf("队列长队为%d\n\n", QueueLength(Q));
	
	DeQueue(&Q, &e); 
	printf("删除的对头元素为%d\n\n", e);
	
	//printf("队列长队为%d\n\n", QueueLength(Q));
	
	//获取对头元素,用e返回
	GetHead(Q, &e);
	printf("获取到的对头元素为%d\n\n", e); 
	
	ClearQueue(&Q);
	printf("队列长度%d\n\n", QueueLength(Q)); 
	
	DestoryQueue(&Q);
	
	EmptyQueue(Q) ? printf("队列为空!!\n\n") : printf("队列不为空!\n\n");
	
	
	return 0;
}

void PrintElem(QElemType e){
	printf("%d ", e);
}

你可能感兴趣的:(C学习记录)