队列,循环队列,链式队列

队列的基本概念:

队列(Queue),和栈一样也是一种操作受限的线性表,只允许在一端进行插入,而在表的另一端进行删除。

特点:“先进先出”(First In First Out,FIFO)。

队头(Front):允许删除的一端,又称为队首。

队尾(Rear):允许插入的一端。

空队:不含任何元素的空表。

队列的应用:比如生活中排队买东西,先排队的先购买,平时我们用微信聊天,用键盘进行各种数字的输入,到聊天框中输出,也是队列的应用。

队列的基本操作:

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

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

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

DeQueue(&Q,&x):出队,若队列为空,删除堆头元素,并用x返回

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

定义队列顺序存储类型 

#define MaxSize 50
typedef struct{
	int data[MaxSize];//用静态数组存放队列元素 
	int front,rear;//队头指针和队尾指针 
}SqQueue;

队列初始化

void InitQueue(SqQueue &Q){
	Q.front=Q.rear=0;
}

 当Q.front=Q.rear=0;说明这个队列没有元素,是一个空队。根据图示

当Q.front再次和Q.rear相等,即Q.rear==MaxSize;是一个“假溢出”,其实队列中还有元素没有出队,但给人一种队列已经空的假象,因此Q.rear==MaxSize;并不能作为队列满的条件。

因此我们引出了循环队列

循环队列

循环队列将顺序队列臆造为一个环状的空间。

初始时:Q.front=Q.rear=0;

队首指针进1:Q.front=(Q.front+1)%MaxSize;

队尾指针进1:Q.rear=(Q.rear+1)%MaxSize;

队列长度:(Q.rear+MaxSize-Q.front)%MaxSize;

队满条件:(Q.rear-Q.front)%MaxSize==Q.front;

队空条件:Q.rear==Q.front;

队列中元素的个数:(Q.rear+MaxSize-Q.front)%MaxSize;

 

初始化

void InitQueue(SqQueue &Q){
	Q.front=Q.rear=0;
}

判断队列是否为空

bool isEmpty(SqQueue Q){
	if(Q.front==Q.rear)
	   return true;
	else
	   return false;
}

入队

bool EnQueue(SqQueue &Q,int x){
	if((Q.rear-Q.front)&MaxSize==Q.front))//队满报错 
	   return false;
	Q.data[Q.rear]=x;
	Q.rear=(Q.rear+1)%MaxSize;//队尾指针加1取模 
}

出队

bool DeQueue(SqQueue &Q,int &x){
	if(Q.front==Q,rear) //队空报错 
	  return false;
	x=Q.data[Q.front];
	Q.front=(Q.front+1)&MaxSize;//队头指针加1取模 
} 

在进行循环队列的判断,常常涉及到mod函数(取模),但是取模和取余有着一定的区别

例如:

a = -7;b = 4; a<0

第一步:

①进行求模运算时:c = [a/b] = -7 / 4 = -2(向负无穷方向舍入),

②进行求余运算时:c = [a/b] = -7 / 4 = -1(向0方向舍入);

第二步:

①求模时:r = a - c*b =-7 - (-2)*4 = 1,

②求余时:r = a - c*b = -7 - (-1)*4 =-3。

a = 7;b = 4;a>0(整数取余还是取模没有区别)

第一步:

①进行求模运算c = [a/b] = 7 / 4 = 1

②进行求余运算c = [a/b] = 7 / 4 = 1

第二步:

①求模时:r = a - c*b =7 - (1)*4 = 3,

②求余时:r = a - c*b = 7 - (1)*4 =3。

******C中提供的取模(%)是用来求两个整数相除的余数。关于取模运算例:A mod B,如果A小于或等于B,其结果是A。

 队列的链式存储结构

队列的链式表示,实际上是一个同时带有队头指针和队尾指针的单链表。头指针指向队头结点,为指针指向队尾结点。

队列的链式存储类型

//强调结点 
typedef struct LinkNode{//链式队列结点 
	int data;
	struct LinkNode *next;
}LinkNode;
//强调链式队列 
typedef struct{//链式队列 
	LinkNode *front,*rear;//队列的队头指针和队尾指针 
}*LinkQueue;

初始化

//初始化
void InitQueue(LinkQueue &Q){
	Q.front=Q.rear=(LinkNode *)malloc(sizeof(LinkNode));//为队列分配一个头结点 
	Q.front->next=NULL;//初始为空 
} 

 判断队列是否为空

//判断队列是否为空
bool IsEmpty(LinkQueue Q){
	if(Q.front==Q.rear)
	   return false;
	else
	   return true;
} 

入队操作

void EnQueue(LinkQueue &Q,int x){
	LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));//创建新结点 
	s->data=x;
	s->next=NULL;//插入到链尾 
	Q.rear->next=s;
	Q.rear=s;
} 

出队操作

bool DeQueue(LinkQueue &Q, int &x){
	if(Q.front==Q.rear)//空队 
	   return false;
	LinkNode *p=Q.front->next;
	x=p->data;
	Q.front->next=p->next;
	if(Q.rear=p)//如果p指针指向的结点和尾指针指向的是同一个结点 
	   Q.rear=Q.front;//队列只有一个结点,删除后队列变空
	 free(p);
	 return true; 
}

双端队列

双端队列是指允许两端都可以进行入队和出队操作。将队列的两端分别称为前端和后端。

输出受限的双端队列:允许进行插入和删除,但在另一端只允许插入的双端队列。

输入受限的双端队列:允许进行插入和删除,但在另一端只允许删除的双端队列。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值