王道计算机考研数据结构—学习笔记Chapter Four 队列Queue

4.1队列的定义(逻辑结构)

队列Queue是一种操作受限的线性表。只允许在一端进行插入,在另一端删除的线性表。对头是允许删除的一端,称为对头元素。队尾是允许插入的一端,称为队尾元素。队列的特点是先进先出(FIFO)

4.2队列的基本操作

lnitQueue(&Q):初始化队列。构造一个空队列Q。

DestroyQueue(&Q):销毁队列。销毁并释放队列Q所占用的内存空间。

EnQueue(&Q,x):入队。若队列Q未满,将x加入,使之成为新的队尾。

DeQueue(&Q,&8:出队。若队列Q非空,删除队头元素,并用x返回。

GetHead(Q,&x):读队头元素。若队列Q非空,则将队头元素赋值给x。

QueueEmpty(Q):判队列空。若队列Q为空返回true,否则返回false。

4.3队列的存储结构(物理结构)

4.3.1顺序队列SqQueue

#define MaxSize 10//定义队列中元素的最大个数
typedef struct{
	ElemType data [MaxSize] ;//用静态数组字放队列元素
	int front, rear;//队头指针和队尾指针

}SqQueue;//定义顺序队列



//初始化队列
void InitQueue(SqQueue &Q){
	Q.rear=Q.front=0;//初始时队头、队尾指针指向0

}


//判空操作。判断队列是否为空
bool QueueEmpty(SqQueue Q){
	if(Q.rear==Q.front)	//队空条件
		return true;
	else
		return false;
}

 
 
//入队
bool EnQueue(SqQueue &Q,ElemType x){
	if((Q.rear+1)%MaxSize==Q.front)//判满操作,牺牲一个存储单元 
		return false;//队满则报错
	Q.data[Q.rear]=x;//将x插入队尾
	Q.rear=(Q.rear+1)%MaxSize;//队尾指针加1取模,存储空间上循环队列 
	return true;
}


//出队(删除一个队头元素,并用x返回)
bool DeQueue(SqQueue &Q,ElemType &x){
	if(Q.rear==Q.front)//判断对空操作 ,牺牲一个存储单元
	//或者使用增加size变量的方法记录队列长度
	//或者使用增加tag = 0/1的方法用于标记最近的一次操作是 出队或入队

		return false;//队空则报错
	x=Q.data[Q.front];
	Q.front=(Q.front+1)%MaxSize;//队头指针后移 
	return true;
}


//获得队头元素的值,用x返回
bool GetHead(SqQueue Q,ElemType &x){
	if(Q.rear==Q.front)
		return false;//队空则报错
	x=Q.data[Q.front];
	return true;
}


void testQueue(){
	SqQueue();//定义一个顺序队列 
	InitQueue(Q) ; //初始化顺序队列 
	//...其他代码...
} 

4.3.2链式队列LinkQueue

typedef struct LinkNode{//定义链式队列结点
	ElemType data;
	struct LinkNode *next;
}L inkNode;
typedef struct{//链式队列
	LinkNode *front,*rear; //队列的队头和队尾指针
}LinkQueue;





//1初始化队列(带头结点)
void InitQueue(LinkQueue &Q){//初始时front. rear都指向头结点
	Q. front=Q. rear=(LinkNode* )malloc(sizeof(LinkNode));
	Q. front->next=NULL; 
}
//2判断队列是否为空(带头结点) 
bool IsEmpty(LinkQueue Q){
	if(Q. front==Q. rear)
		return true;
	else
		return false;
}
//3新元素入队(带头结点)
void EnQueue(LinkQueue &Q, ElemType x){
	LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
	s->data=x;
	s->next=NULL;
	Q. rear->next=s;//新结点插入到rear结点之后
	Q.rear=s;//修改表尾rear指针
}
//4对头元素出队(带头结点) 
bool DeQueue(LinkQueue &Q, ElemType &x){
	if(Q. front==Q,rear)
		returnCfalse;//空队
	LinkNode *p=Q. front ->next;
	x=p->data;//用变量x返回队头元素
	Q. front->next=p->next; //修改头结点的 next 指针
	if(Q. rear==p)//此次是最后一个元素结点出队
		Q. rear=Q. front ;	//修改rear指针
	free(p);	//释放结点空间
	return true;
}




//1初始化队列(不带头结点)
void InitQueue( LinkQueue &Q){//初始时front、 rear都指向NULL
	Q. front=NULL;
	Q. rear=NULL; .
}
//2判断队列是否为空(不带头结点)
bool IsEmpty(LinkQueue Q){
	if(Q. front==NULL)
		return true;
	else
		return false;
}
//3新元素入队(不带头结点)
void EnQueue(LinkQueue &Q, ElemType x){
	LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
	s->data=x;
	s->next=NULL;
	if (Q.front == NULL){//在空队列中插入第一个元素
		Q.front = s;//修改队头队尾指针
		Q.rear=s;//不带头结点的队列,第一个元素入队时需要特别处理
	} else {
		Q. rear->next=s;//新结点插入到rear结点之后
		Q.rear=s;//修改表尾rear指针
	}
}
//4队头元素出队(不带头结点)
bool DeQueue (LinkQueue &Q, ElemType &x){
	if(Q. front==NULL)
		return false;//空队
	LinkNode *p=Q. front;	//p指向此次出队的结点
	x=p->data;	//用变量x返回队头元素
	Q. front=p->next;	//修改front 指针
	if(Q. rear==p){	//此次是最后一个结点出队
		Q. front = NULL;	//front指向NULL
		Q.rear = NULL; 	//rear指向NULL,恢复空队 
	}
	free(p);	//释放结点空间
	return true;
}


 
void testLinkQueue(){
	LinkQueue();//声明一个链式队列 
	InitQueue(Q) ; //初始化队列 
	
} 

4.3.2.1链式队列(带头结点)

4.3.2.2链式队列(不带头结点)

顺序存储的预分配的空间耗尽时队满,而链式存储一般不会队满 ,除非内存空间不足。

4.3.2.3双端队列

  • 双端队列是只允许两端插入、两端删除的线性表。
  • 输入受限的双端队列有两类,一种是只允许从一端插入两端删除的线性表,另一种是只允许从一端删除两端插入的线性表。
  • 考点:对输出序列的合法性的判断

4.4队列的应用

Eg1:树的层次遍历

Eg2:图的广度优先遍历

Eg3:在操作系统中的应用,使用先来先服务(FCFS) 策略抢用有限系统资源 ,如打印数据缓冲区。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值