数据结构之线性表(十三)——队列(1 循环队列)

队列类型定义

有关队列的相关概念,可以参考数据结构之线性表(十一)——栈和队列的定义和特点

抽象类型定义如下:
ADT Queue
{
     数据对象: D = { a i ∣ a i ∈ E l e m S e t , i = 1 , 2 , . . . , n , n ≥ 0 } D=\{a_i|a_i \in ElemSet,i=1,2,...,n,n\geq 0 \} D={aiaiElemSet,i=1,2,...,n,n0}
     数据关系: R = { &lt; a i − 1 , a i &gt; ∣ a i − 1 , a i ∈ D , i = 1 , 2 , . . . , n } R=\{&lt;a_{i-1},a_i&gt;|a_{i-1},a_i \in D,i=1,2,...,n\} R={<ai1,ai>ai1,aiD,i=1,2,...,n}
     约定其中 a 1 a_1 a1端为队头, a n a_n an端为队尾。
     基本操作: 有初始化,获取队头元素等操作。
}ADT Queue



顺序队

队列的存储方式也有两种:顺序队列和链式队列。

顺序队列的表示——用一维数组base[MAXQSIZE]

#define MAXQSIZE 100     //队列的最大长度
typedef struct
{
	QElemType* base;     //初始化的动态分配存储空间
	int front;           //头指针,即队头元素下标
	int rear;            //尾指针,即队尾元素下标
};

表示和实现:

  • 新建一个空队列,初始情况为:front=rear=0
    在这里插入图片描述

  • 有元素入队:base[rear]=x;rear++;,例如J1,J2,J3入队
    在这里插入图片描述

  • 有元素出队:x=base[front];front++;,例如J1,J2出队
    在这里插入图片描述

空队标志:```front==rear````

  • 接着上一个的状态,让J4,J5,J6入队,J3,J4出队,如下图,
    *

那么,此时,还可以入队吗?

此时,就发生了问题,即当rear=MAXQSIZE时,发生了溢出

溢出分两种情况:

  • 真溢出:若front=0,rear=MAXQSIZE时,再入队,
    在这里插入图片描述
    这种情况下,该队列确实没有空间存放元素了,所有位置都放满了。
  • 假溢出: f r o n t ≠ 0 front \neq0 front̸=0,rear=MAXQSIZE时,再入队,
    在这里插入图片描述
    这种情况下,该队列并没有满,该队列其实是有存储空间的。

所以,怎么解决假溢出的这种情况呢?

  • 方式一.与现实生活中的排队类似,队头每离开一个元素,剩下的所有元素都往前移一位。
    但是,这种方式有明显的缺点:浪费时间,因为每移动一次,队中元素都要移动。

  • 方式二.引入循环顺序队
    将队空间设想成一个循环的表,即分配给队列的m个空间循环使用,当rear=MAXQSIZE时,若向量的开始端空着,就可以从头使用空着的空间。当front为MAXQSIZE时,也是一样。

base[0]要接在base[MAXQSIZE]之后,若rear+1==M,则令rear=0;
实现方法:利用模运算
插入元素Q.base[Q.rear]=x;Q.rear=(Q.rear+1)%MAXQSIZE;
删除元素x=Q.base[s.front];Q.front=(Qfront+1)%MAXQSIZE;



循环顺序队

在循环顺序队里,队空和队满的标志都是front==rear,如下图,
在这里插入图片描述

如何判断循环顺序队的队空或队满?一般有三种方法:

  • 另外设一个标志以区别队空,队满
  • 另外设一个变量,记录元素个数
  • 少用一个元素空间

这里,可以采用第三种——少用一个元素空间。

  • 一般情况如下图,
    在这里插入图片描述
  • 而少用一个元素空间为:
    在这里插入图片描述
    此时,判断队满的标志是:(rear+1)%MAXQSIZE==front。


循环队列里的各项操作

  • 循环队列初始化
Status InitQueue(SqQueue& Q)
{
	Q.base = new QElemType[MAXQSIZE];   //分配数组空间
	if (!Q.base)
		exit(OVERFLOW);                 //存储分配失败
	Q.front = Q.rear = 0;               //头指针尾指针设为0,队列为空
	return OK;
}
  • 求循环队列的长度
int QueueLength(SqQueue Q)
{
	return ((Q.rear - Q.front + MAXQSIZE) % MAXQSIZE);
}
  • 循环队列入队
Status EnQueue(SqQueue& Q, QElemType e)
{
	if ((Q.rear + 1) % MAXQSIZE == front)   //队满
		return ERROR;
	Q.base[Q.rear] = e;                     //新元素加入队尾
	Q.rear = (Q.rear + 1) % MAXQSIZE;       //队尾指针加1
	return OK;
}
  • 循环队列出队
Status EnQueue(SqQueue& Q, QElemType& e)
{ 
	if (Q.front == Q.rear)                 //队空
		return ERROR;                     
	e = Q.base[Q.front];                   //保存队头元素
	Q.front = (Q.front + 1) % MAXQSIZE;    //队头指针加1
}
  • 循环队列取队头元素
SElemType GetHead(SqQueue Q)
{
	if (Q.front != Q.rear)              //队列不为空
		return Q.base[Q.front];         //返回队头指针元素的值,队头指针不变
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值