队列的链式存储--- 2021.10.27

2023-05-16

上一讲链接:

队列的基本概念— 2021.10.8

队列的链式存储:

什么叫队列的链式存储呢?我们在上一讲都知道队列的结构特点,那么我们可不可以通过链表来实现队列,从而实现了队列的链式存储。

那么接下来我们一起来探讨吧!!!

那我们现在先思考一个问题:链表的头节点是做队头还是做队尾?

由于队列具备先进先出的特性,所以我们在插入数据和删除数据时总是会从队头出,从队尾入。所以链表的头节点做队头比较合适。

接下来就开始根据代码具体分析:

//初始化队列
LinkQueue init_LinkQueue()
{
	struct LQueue * myQueue = malloc(sizeof(struct LQueue));
	if (myQueue == NULL)
	{
		return NULL;
	}

	myQueue->m_Size = 0;
	myQueue->pHeader.next = NULL;
	myQueue->pTail = &myQueue->pHeader; //尾节点开始指向的就是头节点
	return myQueue;
}
//入队
void push_LinkQueue(LinkQueue queue, void * data)
{
	//等价于 尾插
	if (queue == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct LQueue * myQueue = queue;
	struct QueueNode * myNode = data; 
	
	//更改指针指向
	myQueue->pTail->next = myNode;
	myNode->next = NULL;
	//更新尾节点
	myQueue->pTail = myNode;

	//更新队列大小
	myQueue->m_Size++;
}
//出队
void pop_LinkQueue(LinkQueue queue)
{
	//等价于 头删 

	if (queue == NULL)
	{
		return;
	}
	struct LQueue * myQueue = queue;

	if (myQueue->m_Size == 0)
	{
		return;
	}

	if (myQueue->m_Size == 1)
	{
		myQueue->pHeader.next = NULL;
		myQueue->pTail = &myQueue->pHeader; //维护尾节点指针
		myQueue->m_Size = 0;
		return;
	}

	//记录第一个节点
	struct QueueNode * pFirst = myQueue->pHeader.next;
	myQueue->pHeader.next = pFirst->next;
	//更新队列大小
	myQueue->m_Size--;
}
//返回队头
void * front_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}
	struct LQueue * myQueue = queue;

	return myQueue->pHeader.next;
}
//返回队尾
void * back_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}
	struct LQueue * myQueue = queue;

	return myQueue->pTail;
}
//返回队列大小
int size_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}
	struct LQueue * myQueue = queue;

	return myQueue->m_Size;
}
//判断队列是否为空
int isEmpty_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}
	struct LQueue * myQueue = queue;

	if (myQueue->m_Size == 0)
	{
		return 1;
	}

	return 0;
}
//销毁队列
void destroy_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return;
	}
	free(queue);
	queue = NULL;
}

我们还是按照老样子,对上述代码进行逐句分析:

LinkQueue init_LinkQueue()
{
	struct LQueue * myQueue = malloc(sizeof(struct LQueue));
	if (myQueue == NULL)
	{
		return NULL;
	}

	myQueue->m_Size = 0;
	myQueue->pHeader.next = NULL;
	myQueue->pTail = &myQueue->pHeader; //尾节点开始指向的就是头节点
	return myQueue;
}

对该段代码解释如下:
首先我们需要在堆区中申请一段内存空间用来存放队列,即malloc函数。其中LQueue是我们自己定义好的队列结构体,其中的成员变量有头节点,队列的大小,还有记录尾节点的指针(因为我们插入数据时要进行尾插操作),具体代码如下:

struct LQueue
{
	struct QueueNode pHeader; //头节点
	int m_Size; //队列的大小
	struct QueueNode * pTail; //记录尾节点的指针
};

成功建立好队列之后,为了算法的严谨,需要对判断是否申请成功内存空间,如果为空,则自动退出该函数,不再往下进行。
由于该函数为初始化队列函数,所以需要如上述代码一样,设置队列的大小为0,设置头节点的指针域为空,设置尾节点的指
向为头节点,因为队列此时只有一个头节点。

void push_LinkQueue(LinkQueue queue, void * data)
{
	//等价于 尾插
	if (queue == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct LQueue * myQueue = queue;
	struct QueueNode * myNode = data; 
	
	//更改指针指向
	myQueue->pTail->next = myNode;
	myNode->next = NULL;
	//更新尾节点
	myQueue->pTail = myNode;

	//更新队列大小
	myQueue->m_Size++;
}

对该段代码解释如下:
成功初始化队列之后,我们需要进行入队操作,即向队列中插入数据。

首先为了算法的严谨,我们需要对传入该函数的入口参数进行校验,如果为空,则自动退出该函数,如果不为空,则继续执行。

同理,我们需要创建一个指针来指向该入口参数queue,创建一个指针来指向待插入的数据data

然后此时我们需要更改指针的指向来使得该数据成功插入。经过初始化的队列,只有一个头节点,并且尾节点指向了头节点,所以我们需要先将尾节点的指针域指向待插入数据data,即myNode。然后将myNode的指针域指向空即可。然后尾节点还是指向头节点的状态,所以我们需要更新尾节点的指向,将尾节点的指向到myNode即可,此时队列中存在一个头节点和一个插入的新节点。

最后队列大小累加即可。

void pop_LinkQueue(LinkQueue queue)
{
	//等价于 头删 

	if (queue == NULL)
	{
		return;
	}
	struct LQueue * myQueue = queue;

	if (myQueue->m_Size == 0)
	{
		return;
	}

	if (myQueue->m_Size == 1)
	{
		myQueue->pHeader.next = NULL;
		myQueue->pTail = &myQueue->pHeader; //维护尾节点指针
		myQueue->m_Size = 0;
		return;
	}

	//记录第一个节点
	struct QueueNode * pFirst = myQueue->pHeader.next;

	myQueue->pHeader.next = pFirst->next;

	//更新队列大小
	myQueue->m_Size--;

}

对该段代码解释如下:
跟入队同理,出队相对于对该队列中的节点进行头删。

首先为了算法的严谨,我们需要对传入该函数的入口参数进行校验,如果为空,则自动退出该函数,如果不为空,则继续执行。

同时我们还需要考虑一种情况,即此时如果队列中的大小为0,我们就没有必要进行出队操作了,提前退出即可。

如果队列中的情况为只有一个头节点和一个节点呢?我们需要将这个情况特别处理,即我们需要将头节点的指针域指向空,然后将尾节点指向头节点,更新队列的大小即可。

如果队列中节点数量大于一时,则我们需要先通过创建一个指针pFirst提前保存下第一个节点的位置,因为我们要进行头删。然后将头节点的指针域重新指向pFirst的指针域即可,即删除了第一个节点。

然后更新队列大小即可。

void * front_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}
	struct LQueue * myQueue = queue;

	return myQueue->pHeader.next;

}

对该段代码解释如下:
首先为了算法的严谨,我们需要对传入该函数的入口参数进行校验,如果为空,则自动退出该函数,如果不为空,则继续执行。

通过一个指针来成功访问传入进来的结构体成员。

由于该函数的作用为返回队头,即返回头节点的指针域即可。

void * back_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return NULL;
	}
	struct LQueue * myQueue = queue;

	return myQueue->pTail;

}

对该段代码解释如下:
首先为了算法的严谨,我们需要对传入该函数的入口参数进行校验,如果为空,则自动退出该函数,如果不为空,则继续执行。

通过一个指针来成功访问传入进来的结构体成员。

由于该函数的作用为返回队尾,即返回结构体成员即可。

int size_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}
	struct LQueue * myQueue = queue;

	return myQueue->m_Size;

}

对该段代码解释如下:
首先为了算法的严谨,我们需要对传入该函数的入口参数进行校验,如果为空,则自动退出该函数,如果不为空,则继续执行。

通过一个指针来成功访问传入进来的结构体成员。

由于该函数的作用为返回队列大小,即返回结构体成员即可。

int isEmpty_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return -1;
	}
	struct LQueue * myQueue = queue;

	if (myQueue->m_Size == 0)
	{
		return 1;
	}

	return 0;
}

对该段代码解释如下:
首先为了算法的严谨,我们需要对传入该函数的入口参数进行校验,如果为空,则自动退出该函数,如果不为空,则继续执行。

通过一个指针来成功访问传入进来的结构体成员。

如果队列大小为0,则返回1,如果上述条件都不符合,则返回0

void destroy_LinkQueue(LinkQueue queue)
{
	if (queue == NULL)
	{
		return;
	}
	free(queue);
	queue = NULL;
}

对该段代码解释如下:
首先为了算法的严谨,我们需要对传入该函数的入口参数进行校验,如果为空,则自动退出该函数,如果不为空,则继续执行。

释放掉该创建好的内存空间,然后置空即可。

结束语

如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

队列的链式存储--- 2021.10.27 的相关文章

  • 高翔讲课2021/8/12

    一些笔记精选 xff1a ORBSLAM 学界业界受欢迎的 有些扫地机器人就是直接用ORBSLAM做的 从代码质量到开放程度 xff0c ORB是个不错的选择 GPS本身频率低 xff0c 精度差 xff08 10m左右 xff09 xff
  • 2021 CondaHTTPError: HTTP 000 CONNECTION FAILED for url 的问题终极解决方案

    一 首先执行命令 xff0c 查看自己的镜像源 conda config show channels 二 可以首先删除已经存在的镜像源 xff08 注 xff1a 上述三个镜像源无需删除 xff01 xff01 xff01 xff09 xf
  • 2021-02-07 SONiC SAI结构2 1D Bridge

    SONiC SAI结构2 1D Bridge 以太网交换流水线结构 SONiC SAI对交换机 路由器的报文处理流程建立了标准化的行为模型 即使不同的交换芯片内部实现报文处理的方式各不相同 xff0c 由于行为模型是报文处理过程的抽象描述
  • 2021-02-21 SONiC SAI结构5 VXLAN

    SONiC SAI结构5 VXLAN VXLAN报文处理模型流水线结构 SONiC SAI支持VXLAN协议 xff0c 具备支持VTEP的能力 根据报文处理功能模型的特点 xff0c 不同的功能块可以好像搭积木一样组合在一起形成新的功能
  • uC/OS-III源码下载(版本2009-2021)

    uC OS III源码下载 xff08 新版网站 xff09 下载方式一 官网 xff08 即GitHub方式 xff09 二 CSDN 下载方式 一 官网 xff08 即GitHub方式 xff09 链接 uCOS3官网 点击CODEBA
  • 2021-09-27

    虚拟环境中用pip下载安装包却安装到base环境解决方案 原因解决方案 遇到的问题 xff1a windows环境下进入虚拟环境 xff0c 使用pip install指令安装包时发现没有安装到虚拟环境下 xff0c 而是安装到了base环
  • Redis面试题(2021最新)

    文章目录 概述什么是RedisRedis有哪些优缺点为什么要用 Redis 为什么要用缓存 为什么要用 Redis 而不用 map guava 做缓存 Redis为什么这么快 数据类型Redis有哪些数据类型Redis的应用场景 持久化什么
  • 2021-03-19

    switch语句实现成绩选择 注意强制转换 import java util Scanner public class Grade Switch 64 param args public static void main String ar
  • arXiv Journal 2021-01-11

    想来想去 xff0c 觉得还是把每次在arXiv上扫过的文章简单记录下来 2021 01 11 hep ph 2 papershep th 2 papershep lat 1 paper hep ph 2 papers Title QCD
  • OpenSSH权限提升漏洞(CVE-2021-41617)修复 Centos 7升级Openssh 8.8

    OpenSSH权限提升漏洞 xff08 CVE 2021 41617 xff09 修复 1 准备工作2 安装必须的包3 下载OpenSsh 8 8p14 OpenSsh 解压安装5 配置文件修改6 重启服务7 意外 Centos 7升级Op
  • 2021年Linux技术总结(四):Linux 驱动

    一 裸机驱动开发流程 所谓裸机在这里主要是指系统软件平台没有用到操作系统 在基于ARM处理器平台的软件设计中 xff0c 如果整个系统只需要完成一个相对简单而且独立的任务 xff0c 那么可以不使用操作系统 xff0c 只需要考虑在平台上如
  • 位姿图优化小记2021.10.18

    1 场景描述 现在有一个小车在运动 xff0c 并搭载相机或激光雷达进行建图工作 xff0c 由于SLAM的作用 xff0c 在建图的同时小车也可以进行自身的定位 xff0c 因此建立的地图的参考都是相对于自身坐标系的 xff0c 也就是每
  • 2021-06-18

    AttributeError module torch functional has no attribute relu AttributeError module torch functional has no attribute rel
  • UCOSIII从官网(2021)下载

    官网地址 xff1a https www silabs com developers micrium 注意 xff1a 在进入下载前 可能 要注册一个账号 xff0c 如果可以直接下载的话不用注册也可以 xff0c 如果有小伙伴需要注册账号
  • VsCode+LaTexWorkshop外置PDF预览配置(2021.3.3)

    随着插件版本的升级有些配置命令发生了改变 xff0c 这里只是做个简单记录 xff0c 写的比较粗糙 后面有闲工夫再来做做美工 VsCode一侧配置 34 latex workshop view pdf viewer 34 34 exter
  • 2021年MathorCupD题思路

    某钢材生产制造商的钢材切割流程如图 1 所示 其中开卷上料环节将原材料钢卷放在开卷机上 xff0c 展开放平送至右侧操作区域 xff08 见图 2 xff09 剪切过程在剪切台上完成 xff0c 剪切台上依次有切头剪和圆盘剪 圆盘剪 xff
  • 2021电赛F题视觉教程+代码免费开源

    2021电赛F题视觉教程 43 代码免费开源 最近好多要电赛题的源码 xff0c 其他csdn营销号下载都需要会员或钱 xff0c 正好最近课设又要做一遍电赛小车题 xff0c 哥们先把代码开源了 xff0c 饿死营销号 电赛宝藏链接 xf
  • 2021-11-11 机械臂路径规划学习进展

    机械臂关节空间和末端空间路径规划 关节空间路径规划简单障碍物情况 xff1a 之后搭建复杂障碍物场景 xff1a 测试发现路径规划的两个步骤 xff1a 采用了关节空间进行路径规划的方案 xff0c 原因主要是在关节空间也就是构型空间中 x
  • 2021-10-07

    舵机PWM信号转继电器开关信号 本文由 麦粒电子 撰写 xff0c 并提供相应产品服务 叙述 航模玩家经常需要DIY改装 譬如飞行器做一个投弹的开关 xff0c 船用模型做一个投食机关 再或者弄一些彩灯控制 往往这些功能只需要有一个简单的开
  • 求旋转后的坐标

    坐标点target 中心点center 角度angle 旋转后坐标 function getRotatePoint targetX targetY centerX centerY angle const rotation angle Mat

随机推荐

  • 数据结构| |各类排序的时间复杂度以及稳定性

    各类排序的时间复杂度以及稳定性 插入排序 xff1a 直接插入排序 xff1a O N 2 稳定 希尔排序 xff1a O N 1 3 不稳定 选择排序 xff1a 选择排序 xff1a O N 2 不稳定 堆排序 xff1a O Nlog
  • 安装Nvidia显卡驱动和CUDA

    原链接 http community bwbot org topic 152 网上看到的 xff0c 但是原链接 不过这里安装的是CUDA7 5 xff0c 现在最新的是8 0 可以到官网进行下载 xff0c 记住一定不要选择deb方式 x
  • Linux| |IP地址的三类私有地址

    IP地址的三类私有地址 对于IP地址来说有着三种私有地址 三种私有地址如下 xff1a 10 0 0 0 10 255 255 255 172 16 0 0 172 16 255 255 192 168 0 0 192 168 255 25
  • Linux| |如何高效切换目录

    Linxu如何高效切换目录 前言 Linux下对于目录的切换 xff0c 大家肯定会想到一个命令 xff1a cd命令 cd命令确实方便 xff0c 但是当需要频繁的切换目录的时候 xff0c cd命令可能比较麻烦了 比如 xff1a ho
  • C++| |四种强制类型转化(剖析)

    四种强制类型转换 1 出现的原因 C语言的强制类型转换 xff0c 有着两种 隐式类型转换 显示的强制类型转换 举例 xff1a int main int i 61 1 double d 61 i 隐式类型转换 int p 61 amp i
  • 数据结构| |快速排序,二路快排,三路快排

    快速排序 二路快排 三路快排 1 快速排序 1 概念 快速排序采用分治的思想对数据进行排序 选择一个基准值 将比基准值小的放在基准值的左边 xff0c 其余的 xff08 大于或者等于 xff09 放在右边 然后再对左边和右边继续进行划分
  • socket编程中write、read和send、recv

    write xff08 xff09 与read xff08 xff09 函数send xff08 xff09 与recv xff08 xff09 函数 一旦 xff0c 我们建立好了tcp连接之后 xff0c 我们就可以把得到的fd当作文件
  • Ubuntu上火狐浏览器无法上网的解决方法

    网上有的方法是在浏览器中选择更新 xff0c 后来找到了更加直接好用的方法 xff0c 只需要几行命令就可以 1 在终端中输入sudo apt get update 如果在这一步出现错误 xff0c 显示暂时不能解析域名的情况 xff0c
  • 实现字符串连接函数(strcat)

    在字符串的操作中strcat函数的使用是频繁的 xff0c 那么下面我们来自己实现strcat函数的功能 自定义一个函数将要连接的两个字符串作为参数传入 xff0c 然后将str1赋值给临时变量p 然后p一直向后指 xff0c 直到str1
  • C#开发简单的串口上位机

    采用C 开发上位机非常方便 xff0c 具体步骤如下 xff1a 1 绘制一个上位机的界面 xff0c 如下图所示 xff1a 不要忘记还有下面的串口模块serialPort1 2 初始化部分 xff1a 波特率编辑框中加入需要的波特率 实
  • STM32读取匿名光流数据——与Guidance的光流和超声波做对比测试

    使用两个串口同时读取匿名光流和Guidance数据 xff1a 用以比较两个光流的效果 Github链接 xff1a https github com W yt YuTian Pro tree master Guidance 26Ano R
  • UDP编程笔记

    1 字节序 1 1 概念 是指多字节数据的存储顺序 1 2 分类 小端格式 xff1a 将低位字节数据存储在低地址 大端格式 xff1a 将高位字节数据存储在低地址 1 3 注意 LSB xff1a 低地址 MSB xff1a 高地址 2
  • rviz的简单使用

    原链接 xff1a http community bwbot org 运行测试平台 小强ROS机器人 rviz是ros自带的一个图形化工具 xff0c 可以方便的对ros的程序进行图形化操作 其使用也是比较简单 整体界面如下图所示 界面主要
  • c语言_结构体封装寄存器的用法,以及typedef、 volatile、static、 inline关键字用法

    define span class token constant ELFIN TIMER BASE span span class token number 0xE2500000 span span class token comment
  • Ros—RPLIDAR A2激光雷达安装(hector_mapping算法建图同cartographer_ros建图对比)

    Ros RPLIDAR A2激光雷达安装 hector mapping算法建图同cartographer ros建图对比 因为大部分教程复杂繁琐 xff0c 而且容易失败 便整理总结了一下网上的资料 xff0c 感谢 Cayla和 口袋里的
  • 海康设备xml透传以及DS-K1F100-D8E 设备下发卡 ,读卡

    对接海康5604设备 设置温度上限及下限 设备较多通过demo手动透传不可取 故采用代码方式进行透传 代码记录 方便后续开发找方便 public void setThermal Map lt String Object gt params
  • ROS学习之error解决记录

    目录 虚拟机系统版本 xff1a Ubuntu 20 04 ROS版本 xff1a Noetic 1 15 14 虚拟机系统版本 xff1a Ubuntu 18 04 ROS版本 xff1a Melodic 1 14 13 整理一下平时遇到
  • C语言 带参数的#define中#和##的基本用法

    1 单 的作用是把参数变成字符串 xff1b 2 的作用是连接组合参数名字 xff1b 废话不多说 xff0c 看个简洁的例子就明白了 span class token macro property span class token dir
  • 类的封装--- 2021.10.19

    封装是什么 xff1f 我们都知道C 43 43 有三大特性 xff0c 分别是继承 多态和封装 至于继承和多态我会在之后的文章中进行讲述 xff0c 在本讲中我们只讲类的封装 在上一讲中 xff0c 我们论述了类是什么 xff0c 那么我
  • 队列的链式存储--- 2021.10.27

    上一讲链接 xff1a 队列的基本概念 2021 10 8 队列的链式存储 xff1a 什么叫队列的链式存储呢 xff1f 我们在上一讲都知道队列的结构特点 xff0c 那么我们可不可以通过链表来实现队列 xff0c 从而实现了队列的链式存