数据结构 队列(顺序队列 循环队列 链队列)
目录
- 一.引入
- 二.队列的定义
- 三.队列的抽象数据类型
- 四.队列的存储方式
- 五.队列的顺序存储(不太常用 后面5.4会给出原因)
- 5.1顺序存储队列的基本知识点
- 5.2队列的顺序存储描述
- 5.3顺序存储队列的操作
- 5.3.1初始化
- 5.3.2进队操作
- 5.3.3出队操作
- 5.3.4判空操作
- 5.3.5判满操作
- 5.4假溢出问题
- 六.循环队列
- 6.1循环队列的定义
- 6.2循环队列如何判满/空
- 6.3循环队列的存储结构
- 6.4循环队列的操作
- 6.4.1循环队列的初始化
- 6.4.2循环队列求队列长度
- 6.4.3循环队列入队列操作
- 6.4.4循环队列出队列操作
- 七.队列的链式存储结构
- 7.1链队列示意图
- 7.2链队列结构描述
- 7.3链队列基本操作
- 7.3.1链队列初始化
- 7.3.2链队列入队操作
- 7.3.3链队列出队操作
- 八.总结
一.引入
最近,大家肯定都有排队做核酸检测的经历,检测医生与待检人员相比总是少数的,在所有检测窗口都有人正在检测的情况下,后面的人会被要求等待,直到某一窗口空下来,才可以让最前面等待的人做核酸。
在这一过程中,应用了一种数据结构来实现刚才提到的先进先出的排队功能,这种数据结构就是队列。
二.队列的定义
队列是只允许在一端进行插入操作,而另一端进行删除操作的线性表。
队列是一种先进先出的线性表,简称FIFO,允许插入的一端为队尾;允许删除的一端为队头。
三.队列的抽象数据类型
队列同样是线性表,队列也有类似线性表的各种操作,不同的是插入和删除:插入的是时候在队尾进行,删除的时候在队头进行。
ADT 队列(Queue)
Data
同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。
Operation
InitQueue(*Q): 初始化操作,建立一个空队列Q。
DestroyQueue(*Q): 若队列Q存在,則销毀它。
ClearQueue(*Q): 将队列 Q 清空。
QueueEmpty(Q): 若队列Q为空,送回true,否則退回false。
GetHead(Q, *e): 若队列Q存在且非空,用e返因队列Q的队头元素。
EnQueue(*Q,e): 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
DeQueue(*Q, *e): 刪除队列Q中队头元素,并用e返回其值。
QueueLength(Q): 送回队列Q的元素个教。
endADT
四.队列的存储方式
线性表有顺序存储和链式存储,同样,队列作为一种特殊的线性表,也同样存在这两种存储方式;
下面对这两种存储方式进行详细讲解。
五.队列的顺序存储(不太常用 后面5.4会给出原因)
5.1顺序存储队列的基本知识点
队列的顺序存储分配一块连续的存储单元存放队列中的元素,并附设两个指针 front 和 rear 分别指示队头元素和队尾元素的位置。
设队头指针指向队头元素,队尾指针指向队尾元素的下一个位置。
5.2队列的顺序存储描述
代码如下:
#define MAXSIZE 100
typedef struct {ElemType data[MAXSIZE];int front,rear;
} SqQueue;
5.3顺序存储队列的操作
5.3.1初始化
初始状态(队空):Q.front == Q.rear == 0;
5.3.2进队操作
队不满时,先送值到队尾元素,将队尾指针加1。
5.3.3出队操作
队非空时,先删除队头元素,再将队头指针加1。
5.3.4判空操作
Q.front == Q.rear == 0;
5.3.5判满操作
大家试想Q.rear == MAXSIZE 作为队列已满的条件呢?
这显然是不行的,因为队尾指针在这个过程中可能已经到了最尾端,但是队头指针可能不在初始位置,而是在队列的中间。
因为我们无法对队列进行判满操作,因此就会出现下面“假溢出”的问题。
5.4假溢出问题
下图为队列的假溢出图,即下标 0 和 1 的位置还是空闲的,然而指向队尾的指针rear已经出现了数组越界的错误。为了避免这种越界的情况,一般顺序队列也指循环队列。
所以解决假溢出的办法就是后面满了,就从头开始,因此我们需要引入循环队列。
六.循环队列
6.1循环队列的定义
我们把队列的头尾相接的顺序存储结构称为循环队列。
注意:
对于循环队列来说:我们是将队列臆造成一个环状的空间,即把存储队列元素的表从按逻辑上视为一个环这样方便我们的理解,真实的物理内存不是环状的。
6.2循环队列如何判满/空
在空队列时:front等于rear,当队列满时:也是front等于rear;那么如何判断此时的队列是空是满,以下有两种方法:
- 设置一个标志变量flag,当front= =rear,且flag=0时为队列空,当front= =rear,且flag=1时为队列满。
- 当队列空时,条件就是front=rear,当队列满时,我们修改它的条件,保留一个元素空间。也就是说,当队列满时,数组中还有一个空闲单元,我们就认为此队列满了,如下图所示:
不允许出现以下情况出现:
接下来我们对第二种方式进行实现:
- 队列空的条件:front = = rear
- 队列满的条件:(rear + 1)% QueueSize = = front其中,rear为指向队尾元素的下一位置的指针,front 为指向队头元素的指针。QueueSize为队列的最大长度。
- 通用计算队列长度公式:
(rear - front + QueueSize) % QueueSize
6.3循环队列的存储结构
代码如下:
typedef int QElemtype;
typedef struct
{QElemtype data[MAXSIZE];int front; //头指针int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
}SqQueue;
6.4循环队列的操作
6.4.1循环队列的初始化
代码如下:
//初始化一个空队列
bool InitQueue(SaQueue *Q)
{Q->front=0;Q->rear=0;return true;
}
6.4.2循环队列求队列长度
注意: 这个公式一定要记住,很重要:
(Q.rear-Q.front+MAXSIZE)%MAXSIZE;
代码如下:
//返回Q的元素个数,也是队列的当前长度
int QueueLength(SqQueue Q)
{return (Q.rear-Q.front+MAXSIZE)%MAXSIZE;
}
6.4.3循环队列入队列操作
代码如下:
//若队列未满,则插入元素e为Q新的队尾元素
bool EnQUeue(SqQueue *Q,QElemType e)
{if ((Q->rear+1)%MAXSIZE==Q->front)//队列满的判断return FALSE;Q->data[Q->rear]=e;//将元素e赋值给队尾Q->rear=(Q->rear+1)%MAXSIZE;//rear指针向后移一位置//若到最后则转到数组头部return TRUE;
}
6.4.4循环队列出队列操作
代码如下:
//若队列不空,则删除Q中队头,用e返回其值
bool DeQueue(SqQueue *Q,QELemType *e)
{if( Q->front==Q->reat=r) //队列空的判断return FALSE;*e =Q->data[Q->front];//将队头元素赋值给eQ->front=(Q->front+1)%MAXSIZE;//front指针向后移一位置//若到最后则转到数组头部return TRUE;
}
循环队列还会面临着数组溢出的问题,所以下一部分我们将会讲解不用担心队列长度的链式存储结构。
七.队列的链式存储结构
队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。
7.1链队列示意图
为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向终端结点。
示意图如下:
空队列时,front和rear都指向头结点,如图所示:
7.2链队列结构描述
代码如下:
typedef struct LinkNode{ElemType data;struct LinkNode* next;
}LinkNode;
typedef struct{LinkNode *front, *rear;
}LinkQueue;
7.3链队列基本操作
7.3.1链队列初始化
代码如下:
void InitQueue(LinkQueue& Q){//初始化时,Q.front 和 Q.rear 同时指向头结点Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));Q.front->next = nullptr;
}
7.3.2链队列入队操作
入队操作,就是在链表尾部插入节点,示意图如下:
代码如下:
bool EnQueue(LinkQueue& Q, ElemType x){LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));s->data = x;s->next = nullptr;Q.rear->next = s; //步骤(1)Q.rear = s; //步骤(2)return true;
}
7.3.3链队列出队操作
出队操作就是头结点的后继结点出队,将头结点的后继改为它后面的结点,若链表除头结点外只剩一个元素时,则需将rear指向头结点;示意图如下:
代码如下:
bool DeQueue(LinkQueue& Q, ElemType &x){if( Q.rear == Q.front ){return false;}LinkNode* p = Q.front->next; //因为有头结点,所以队头节点为Q.front->next //(1)步骤x = p->data;Q.front->next = p->next; //(2)步骤if( Q.rear == p ){ //只剩一个结点,删除后变空只剩头结点Q.rear = Q.front;}free(p);return true;
}
八.总结
对于循环队列与链队列的比较,可以从两方面来考虑:
时间上 | 空间上 |
---|---|
循环队列事先申请号空间,使用期间不释放 | 循环队列必须有一个固定的长度,所以就有存储元素和空间浪费的问题 |
链队列每次申请和释放结点也会存在一些时间开销 | 链队列不会存在上述问题,尽管需要一个指针域,有空间消耗但可以接受 |
总的来说:在可以确定队列长度最大值的情况下,建议用循环队列,如果你无法预估队列的长度时,则使用链队列。
数据结构 队列(顺序队列 循环队列 链队列)相关推荐
- 【数据结构(C++)】用链队列计算杨辉三角
目录 第一节 概述 第二节 开源代码 第一节 概述 杨辉三角是二项式系数在三角形中的一种几何排列,是中国古代数学的杰出研究成果之一.它把二项式系数图形化,把组合数内在的一些代数性质直观地从图形中体现出 ...
- 【C++算法与数据结构学习笔记------用循环数组实现队列】
照王晓东<数据结构>(C++语言版)上打的,以备留用. 1 #include <iostream> 2 using namespace std; 3 template<t ...
- 数据结构与算法(3-2)队列(顺序队列、循环队列与链队列)
目录 一.顺序队列 1.存储结构 2.入队和出队 总代码 二.循环队列 总代码: 三.链队列 1.存储结构 2.入队和出队 总代码 一.顺序队列 队列特征:先进后出.后进后出. 1.存储结构 //队列 ...
- c语言循环队列入列算法,C语言——循环队列和链队列的基本运算
// 循环队列 #include #include "SeqQue.h" // 循环队列的基本运算 /* const int maxsize = 20; typedef struc ...
- 《恋上数据结构第1季》队列、双端队列、循环队列、循环双端队列
队列(Queue) 队列 Queue 队列的接口设计 队列源码 双端队列 Deque 双端队列接口设计 双端队列源码 循环队列 Circle Queue 循环队列实现 索引映射封装 循环队列 – %运 ...
- 数据结构(严蔚敏)之六——链式队列c语言实现
实验: 编写一个程序实现链队列的各种基本运算,并在此基础上设计一个主程序,完成如下功能: (1)初始化并建立链队列 (2)入链队列 (3)出链队列 (4)遍历链队列 分析: 队列的链式存储结构简称为链 ...
- 《数据结构C语言版》——栈和队列详解(图文并茂),从零开始的学习
哈喽!这里是一只派大鑫,不是派大星.本着基础不牢,地动山摇的学习态度,从基础的C语言语法讲到算法再到更高级的语法及框架的学习.更好地让同样热爱编程(或是应付期末考试 狗头.jpg)的大家能够在学习阶段 ...
- 【练习】c++分别用链队列和普通队列输出杨辉三角
普通队列: class queue {public:queue();bool empty()const;bool full() const;int get_front(int& x)const ...
- 【数据结构】队列-顺序队列、循环队列、链队、双端队列
定义 队列是只允许在一端进行插入,而在另一端进行删除的线性表. 队头(Front):允许删除的一端,又称为队首. 队尾(Rear): 允许插入的一端. 先进入队列的元素必然先离开队列,即先进先出(Fi ...
最新文章
- 一年融4轮,虎赞科技完成红杉领投3000万美元B轮融资
- (jQuery,YUI)哪一个适合我?
- nginx 服务器的学习(1)
- crf linux使用教程,Linux下CRF++的使用
- Js中的数据属性和访问器属性
- STM32F407VG uCOS-II2.91 IAR工程 以及uCOS使用库编译的方法
- python布尔类型运算_Python bool类型和比较运算符(入门必读)
- MyBatis学习笔记(2)-MyBatis入门
- 第四季-专题10-字符设备驱动模型
- hashmap 和 hashtable 的区别和联系
- 微信小程序获取公众号文章列表及显示文章
- web切图怎么做_Web前端切图快捷键、技巧和经验
- IBM Power小型机用前面板液晶屏查看HMC端口IP
- HashMap源码分析与实现
- centos php安装 pecl,pecl是什么?如何在centos下安装pecl?
- 闲云野鹤:吃鸡(一)之场景制作:使用GPU instancing方式制作刷草插件
- 企业成功的秘密:成为独角兽
- restapi是什么意思_网上整理的对于Rest和Restful api的理解
- java素数对算法_Java版本 质数(也叫素数)算法
- 诙谐幽默的个性自我介绍
热门文章
- MySQL高级---索引优化分析(Explain性能分析 一)
- 【档案专题】一、电子档案
- 人大李崇轩:我的生成模型修炼之路丨智源大会嘉宾风采
- 计算机毕业设计系列基于JavaWeb的医院挂号预约管理系统
- CPU的发展历史和工作原理
- 日常记录(关于sessionStorage.setItem)
- 关于localstorage.setItem的内容
- 手机电子邮件服务器是什么,什么是电子邮件服务器名?在哪找到接收邮件服 – 手机爱问...
- matlab 跳转到函数,matlab中fmincon函数如何调用??
- 小白学习DirectX11:第一个demo