4.线性结构——队列

队列的定义

队列(queue)是只允许在一段进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出(First In First Out)的线性表,简称FIFO,允许插入的一段称为队尾,允许删除的一段称为队头。
在这里插入图片描述

队列的抽象数据类型

同样是线性表,队列也有类似线性表的各种操作,不同的是插入数据只能在队尾进行,删除数据只能在队头进行。
在这里插入图片描述

循环队列

队列顺序存储的不足

  • 入队列操作,即在队尾追加一个元素,不需要移动任何元素,因此时间复杂度为O(1)。
    在这里插入图片描述
  • 出列:队列元素的出列是在队头,即下标为 0 的位置,那也就意味着,队列中的所有元素都得向前移动,以保证队列的队头,也就下标为 0 的位置不为空。此时时间复杂度为O(n)。
    在这里插入图片描述

队头不需一定在下标为 0 的位置

在这里插入图片描述
为了避免当只有一个元素时,队头与队尾重合使处理变得麻烦,所以引入两个指针

front 指针指向队头元素,rear 指针指向队尾元素的下一个位置,这样当 front 等于 rear 时,此队列不是还剩一个元素,而是空队列。
出现问题:

  1. rear 指针移动到数组之外在这里插入图片描述
  2. 假设这个队列的总个数不超过 5 个,但目前如果接着入队的话,因数组末尾元素已经被占用,再向后加,就会产生数组越界的错误,可实际上,我们的队列还在下标为 0 和 1 和地方还是空的,我们把这种现象叫做“假溢出”。

循环队列定义(解决上述假溢出)

我们把队列的这种头尾相接的顺序存储结构成为循环队列。

问题:

  • 当 front 等于 rear 时,如何判断此时的队列是空还是满?
    办法:(1)设置一个标志变量 flag ,当 front == rear ,且 flag = 0时为队列空,当 front ==rear,且 flag = 1为队列满,
    (2)当队列空时,条件就是 front = rear ,当队列满时,我们修改其条件,保留一个元素空间,也就是说,队列满时,数组中还有一个空闲单元。

在这里插入图片描述

判断队列有没有满

利用第二中方法,由于rear 可能比 front 大,也可能比 front 小,若队列的最大尺寸是 QueueSize,那么队列满的条件为 :

(rear + 1) % QueueSize == front

取模的目的是为了整合 rear 与 front 大小为一个问题。
如上图所示,QueueSize = 5

  • 左图 front = 0, 而 rear = 4,(4+1)% 5 = 0 ,所以此时队列满。
  • 右图 front = 2, 而 rear = 1,(1 + 1)% 5 = 2,所以此时队列也是满的。
  • 对于下面这张图,front = 2, 而 rear = 0,(0 + 1)% 5 = 1,1 ≠ 2,所以此时队列并没有满。
    在这里插入图片描述
    通用的计算队列长度公式:
(rear - front + QueueSize)% QueueSize

循环队列的顺序存储结构代码:

/* 循环队列的顺序存储结构 */
typedef struct
{
	QElemType data[MAXSIZE];
	int front;    	/* 头指针 */
	int rear;		/* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
}SqQueue;

循环队列的初始化代码如下:

/* 初始化一个空队列 Q */
Status InitQueue(SqQueue *Q)
{
	Q->front=0;
	Q->rear=0;
	return  OK;
}

循环队列求队列长度代码如下:

/* 返回Q的元素个数,也就是队列的当前长度 */
int QueueLength(SqQueue Q)
{
	return  (Q.rear-Q.front+MAXSIZE)%MAXSIZE;
}

循环队列的入队操作代码如下:

/* 若队列未满,则插入元素e为Q新的队尾元素 */
Status EnQueue(SqQueue *Q,QElemType e)
{
	if ((Q->rear+1)%MAXSIZE == Q->front)	/* 队列满的判断 */
		return ERROR;
	Q->data[Q->rear]=e;			/* 将元素e赋值给队尾 */
	Q->rear=(Q->rear+1)%MAXSIZE;/* rear指针向后移一位置, */
								/* 若到最后则转到数组头部 */
	return  OK;
}

循环队列的出队列操作代码:

/* 若队列不空,则删除Q中队头元素,用e返回其值 */
Status DeQueue(SqQueue *Q,QElemType *e)
{
	if (Q->front == Q->rear)			/* 队列空的判断 */
		return ERROR;
	*e=Q->data[Q->front];				/* 将队头元素赋值给e */
	Q->front=(Q->front+1)%MAXSIZE;	/* front指针向后移一位置, */
									/* 若到最后则转到数组头部 */
	return  OK;
}

循环队列可能面临数组溢出的问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值