《数据结构打卡》第16天(队列篇)

《数据结构打卡》第16天(队列篇)

距离上一次更新隔了也有15天之久了,在家里的这段时间真的过得蛮快的,但是也是昨天跟今天一样,今天跟明天一样,循环往复着;

队列的定义:

  1. 队列是操作受限的线性表,队列的插入在队尾,队列的删除在队头,
  2. 队列是先进先出的线性表

1、什么是队列的上溢现象?一般有几种解决方法,试简述之?
答:…
当队列中还有剩余空间,入队时却出现队满的情况,一般是因为队满条件设置不合理造成的,称之为“假溢出”。
总共有三种方法解决队列的假溢出:
方法一:增设一个存储队列元素个数的变量num,当num=0时队空,当num=MaxQSize 时为队满;
方法二:设置一个flag标志,当front =rear且flag =0时,则队空,当front=rear且flag = 1时,则队满。
方法三:采取少用一个存储单元的方式,引入循环队列,则队满时队列中还剩一个空闲单元,即队空条件:front == rear,队满条件:(rear+1) % MaxQSize == front,队列长度为(rear-front+MaxQSize) % MaxQSize。

顺序队列抽象数据类型定义:

typedef struct{
	QElemType data[MaxQSize];//定义队列的存储容量,用于存储队列中元素
	int front,rear; //队头和队尾指针
}//SqQueue 顺序队的类型

1.顺序队列的要素
队空条件:Q.front == Q.rear
队满条件:Q.front == MaxQSize -1(数组的最大下标)
队满条件:也可以是Q->rear==Q->front= =n
其实和栈的栈空栈满条件很相似,
栈空是s.top == -1;
栈满是s.top == MaxSize -1;

顺序队的初始化

void InitQueue(SqQueue &q){
	Q=(Squeue * )malloc(sizeof(Squeue)); //分配顺序队列
	Q.front = Q.rear = -1;
}

顺序队的入队EnQueue(&Q,e):

入队:队尾指针先加适用于队尾指针指向最后一个元素的下一个位置:而尾指针后加的情况适用于队尾指针指向最后一个元素的当前位置。

void EnQueue(SqQueue &Q,QElemType e){
	if(Q.front == MaxQSize-1) //1.判断顺序队是否队满
		return error;
	Q.rear++; //2.先移动队尾指针
	Q.data[Q.rear] = e; //3.再入队元素
	
}

顺序队的出队DeQueue(&Q,&e):

void DeQueue(SqQueue &Q,QElmeType &e){
	if(Q.front == Q.rear) //1.判断队列是否为空
		return error;
	Q.front++ //2.先移动队头指针
	e = Q.data[Q.front] //2.再用e出队元素
	
}

销毁队列,判断队空。

void DestroyQueue(SqQueue &Q){ 
 	free(Q) 
 }
bool QueueEmpty(SqQueue &Q){
	return(Q.front == Q.rear) //若队列为空返回真,若不为空返回假
}

2.循环队列的三要素
队空条件:Q.front == Q.rear
队满条件:(Q.rear+1) % MaxQSize == Q.front
队列长度:(Q.rear-Q.front+MaxQSize) % MaxQSize
入队 rear指针循环增1:Q.rear = (Q.rear+1) % MaxQSize
出队 front指针循环增1:Q.front = (Q.front+1) % MaxQSize

//一般情况下,循环队列采用队头front指向当前第一个元素的位置,rear指向最后一个元素的下一个位置。

循环队列的初始化

void InitQueue(SqQueue &Q){
	Q = (SqQueue * )malloc(sizeof(SqQueue )) //分配队列空间
	Q.front = Q.rear = 0; //队头队尾指针指向一起
	//其实循环队列和顺序队列的初始化是一样的,不过教材上硬是要把顺序队列中队头队尾指针设为-1,而循环队列中则把队头队尾指针在初始化时指向0
}

循环队列的入队、出队、求队列长度:
这里入队和出队统一按照先移动队头或队尾指针,然后再入队或出队元素

Status EnQueue(SqQueue &Q,QElemType Q){
	if((Q.rear+1) % MaxQSize == Q.front) //1.判断队满
		return error;
	Q.rear = (Q.rear+1) % MaxQSize; //2.先队尾指针循环增1
	Q.data[Q.rear] = e; //3.后元素e入队
	return ok;
}
Status DeQueue(SqQueue &Q,QElemType &Q){
	if(Q.front == Q.rear) //1.判断队列是否为空
		return error;
	Q.front = (Q.front+1) % MaxQSize //2.先队头指针循环增1
	e = Q.data[Q.front]; //3.后用e取出队头元素
		return ok;
}
int LengthQueue(SqQueue &Q){
	return (Q.rear-Q.front+MaxQSize) % MaxQSize
	//(指向队尾元素下一位置rear指针 - 队头元素指针 + 队列最大容量) % 队列最大容量 = 队列长度
}

3.链式队列的要素

  1. 队空的条件为:Q.rear->next == Null
  2. 和链式栈一样,不考虑队满的情况

链式队列的入队:
①生成新结点存放元素e,由p指针指向。
②将结点p从队尾插入,再由队尾指针指向它。

Status EnQueue(LinkQueue &Q,QElmeType e){
	QNode = *p; //声明p指针,用于元素入队
	p = (QNode * )malloc(sizeof(QNode)); //1.p指向新创建的结点
	//或 p = new QNode;
	p->data = e; //p的data域赋值
	p->next = Null; //p结点插入在队尾,所以next域一定要置空
	//链式队的入队不考虑队满的情况
	if(Q.rear->next == Null) //若队列为空
		Q.front=Q.rear = p; //2.则队头队尾指针均指向p结点
	else{ //队列中存在结点
		//以下两步才是最重要的
		Q.rear->next = p; //3.rear指针先链接p结点
		Q.rear = p; //4.然后rear指针指向新插入的尾结点
	}
	return ok;		
}

链式队列的出队:
①使用元素e取出队头元素,
②然后队头指针后移,指向下一结点。

Status DeQueue(LinkQueue &Q,ElemType &e){
	QNode = *p; //声明p指针,用于元素出队
	if(Q.rear->next == Null) //判断链队列是否为空
		return error; 
	p=Q.front->next  //1.先让P结点指向头结点的下一个结点
	e=p->data; //2.再用e返回p结点data域的值
	Q.front->next = p->next;  //3.修改指针,头指针指向将要被删除
	//结点的后继结点。
	delete p; //4.删除p所指结点
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值