【数据结构】队列

文章介绍了队列这一数据结构的概念,包括其作为FirstInFirstOut(FIFO)的数据特性。队列可以用静态数组或链表来实现,文中详细阐述了顺序存储结构中队列的初始化、判断队空队满、入队、出队等操作,并讨论了循环队列的实现方式。此外,还提到了链式结构实现队列的优缺点以及双端队列的概念。
摘要由CSDN通过智能技术生成

概念

队列也是操作受限的线性表
队尾:允许插入的一端
队头:允许删除的一端
队列的特点:First In First Out(先进先出)(FIFO)
基本操作:
初始化、销毁、入队、出队、读队头元素、判空

用顺序存储实现队列

代码:用静态数组存放队列元素

#define MaxSize 10
typedef struct
{
ElemType data[MaxSize];
int front;//定义队头指针
int rear;//定义队尾指针
}SqQueue

定义一个函数声明队列

void testQueue()
{
SqQueue Q;//声明一个队列
}

队头指针指向队头元素
队尾指针指向队尾元素的后一个元素

初始化队列

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

判断是否为空

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

入队

入队要先判队满

bool EnQueue(SqQueue &Q,ElemType x)
{
if(队列满)
return false;
Q.data[Q.rear]=x;//将数据放到队尾
Q.rear=(Q.rear+1)%MaxSize;//队尾指针后移一位 即+1取模
return true;
}

队尾指针后一移位不是简单的加1,是加1取模

循环队列

将线性的存储空间,在逻辑上变成了环状。

判断队列已满的条件

队尾指针的再下一个位置是队头

(Q.rear+1)%MaxSize==Q.front

出队(删)

bool DeQueue(SqQueue &Q,ElemType &x)
//先判空
if(Q.rear == Q.front)
return false;
x=Q.data[Q.front];
Q.front = (Q.front+1)%MaxSize;//队头指针后移
return true;
}

求队列的元素个数

n=(rear+MaxSize-front)%MaxSize

判断队满和队空的三种方式

第一种

队尾指针的再下一个位置是队头->队满

(Q.rear+1)%MaxSize==Q.front

第二种

在队列的结构中定义一个变量size,来记录队列中此时有多少个元素。
插入成功size++,删除成功size–

#define MaxSize 10
typedef struct
{
ElemType data[MaxSize];
int front,rear;
int size;//队列当前长度
}SqQueue;

第三种

#define MaxSize 10
typedef struct
{
ElemType data[MaxSize];
int front,rear;
int tag;
}SqQueue;

tag=0;最近进行删除操作
tag=1;最近进行插入操作
只有删除操作会导致队空,插入操作会导致队满
队满的条件:(插入导致队满 所以tag=1)

front==rear && tag==1

队空的条件

front==rear && tag==0

当队尾指针指向的就是队尾元素

在这里插入图片描述在这里插入图片描述

队列的链式实现

在这里插入图片描述

不同于单链表,队列的链式实现需要一个带头结点和尾结点的单链表。
当在只带头结点的单链表的尾部插入数据时,需要一直遍历到尾部,时间复杂度是O(n)
在给队列进行出队操作时,只需要找到头结点
在这里插入图片描述

初始化(带头结点)

在这里插入图片描述

初始化(不带头结点)

在这里插入图片描述入队操作队尾,出队操作队头

入队(带头结点)

一开始时:
在这里插入图片描述

s->data=x;
s->next=NULL;
Q.rear->next=s;
//不要忘了修改表尾指针
Q.rear=s;

不要忘了最后一步修改表尾指针
在这里插入图片描述

入队(不带头结点)

在这里插入图片描述首先申请一个新结点,给新结点写入数据x。s->data=x
因为每次入队的结点都是队列中的新结点,所以
s->next=NULL

出队(带头结点)

第一步:判空

if(Q.front==Q.rear)
return false;

第二步:将p指针指向此次要删除的结点
对于带头结点的队列来说,此次要删除的就是虚拟头指针指向的下一个结点(真正的头结点)

LinkNode* p = Q.front->next;
x=p->data;
Q.front->next = p->next;//将p删掉
//如果是最后一个结点出队
if(Q.rear==p)
{
Q.rear=Q.front;//删完队列空了
}
free(p);

在这里插入图片描述

出队(不带头结点)

在这里插入图片描述

队列满的条件

在这里插入图片描述

双端队列

双端队列:只允许从两端插入、两端删除的线性表
在这里插入图片描述

例子

在这里插入图片描述在这里插入图片描述在这里插入图片描述

选择题

1.(C)

这里是引用

数组A[n]的下标范围0~n-1。即MaxSize=n
则队列长度 (rear-front+MaxSize)%MaxSize=(3-8+21)%21=16

这里是引用

队列:入队在队尾,出队在队头。而队尾在链表的表头,队头在链表的表尾。

队列需要在双端操作,所以对于单链表必须要带头指针和尾指针。改成循环链表是画蛇添足,没这个必要
只带队首指针的非循环双链表,只能在队头操作,不适合在队尾操作
3.(A)

这里是引用

进队是在队尾,题目中链表只有头指针,没说有头结点或是尾指针,进队后在链表头插,又因为题目是循环单链表,所以需要找到尾结点,需要一直遍历到尾结点,时间复杂度为O(n)。

4.(A)

这里是引用

第一个进入队列的元素存储在A[0]处,对于元素进队的操作为:Q.rear=(Q.rear+1)%MaxSize
MaxSize=n
Q.rear=n-1

5.n至少是4

这里是引用

入队顺序8,4,2,5,3,9,1,6,7
出队顺序1,2,3,4,5,6,7,8,9
分组
A组:8,9
B组:4,5,6,7
C组:2,3
D组:1,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值