重生之我在学数据结构——队列

一.队列的概念

队列是一种先进先出(First In First Out ,FIFO)的数据结构,可以简单理解为排队的概念。在队列中,数据项按照插入的顺序排列,并且只能在队列的一端插入(称为队尾),在另一端删除(称为队头)。

先进先出的概念就是先进队列的数据就会先出队列。比如入队顺序为1、2、3、4,那么出队列的顺序只有1、2、3、4这一种可能性。 

如果我们要选择结构来实现队列的话,应该选谁呢?

数组的话,因为涉及到队头出数据。数组的话,删除第一个数据的话,后面所有的数据都得往前挪,所以我们不考虑数据。

单链表的话,入数据就是尾插,出数据就是头删。队列会频繁的插入与删除数据,而链表相比于数组的有点就在于可以频繁的插入删除。所以我们可以利用单链表来实现队列。

二.队列结构的设计

队列既然要由链表实现,那么我们就要设计节点。节点只需要有数据域(保存队列待存的数据)和指针域(指向下一个节点的指针)。

在队列中,涉及的入数据和出数据分别对应着链表的头和尾,所以我们需要定义一个头节点和一个尾节点。

根据以上两点,我们可以先设计出队列节点的结构:

typedef int QueueDataType;//队列中的节点
typedef struct QueueListNode
{QueueDataType a;struct QueueListNode* next;
}QueueNode;

而对于一条队列来说,我们需要头节点和尾节点,所以我们可以在创建一个结构体Queue,专门用来维护队列。

队列中有的接口是返回有效元素的个数,我们可以在维护队列的结构体中加一个size变量,用来记录当前队列的有效元素个数。如果不这样的话,我们就得遍历链表,会浪费时间。

//队列
typedef struct Queue
{QueueNode* _front;QueueNode* _back;int size;
}Queue;

三.队列的初始化和销毁

3.1队列的初始化

队列初始化,也就是对头节点和尾节点的初始化,我们开始时没有必要开辟空间,只需要在插入数据时在malloc空间即可。所以我们刚开始直接让头尾节点的指针指向NULL,size置为0。

//队列的初始化
void QueueInit(Queue* pq)
{assert(pq);pq->_front = NULL;pq->_back = NULL;pq->size = 0;
}

3.2队列的销毁

我们前面设计,由一条单链表来维护队列,所以队列的销毁其实就是链表的销毁。我们只需要遍历链表,一个节点一个节点的销毁即可。

//队列的销毁
void QueueDestroy(Queue* pq)
{assert(pq);QueueNode* cur = pq->_front;while (cur){QueueNode* next = cur->next;free(cur);cur = next;}pq->_front = NULL;pq->_back = NULL;pq->size = 0;
}

四.入队列

队列插入数据的时候只能从队尾进行插入,对于单链表来说其实就是尾插。要注意的就是,每插入一个数据,size就要++。

//入队尾
void QueuePush(Queue* pq, QueueDataType x)
{assert(pq);//创建新节点QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("QueuePush()::malloc()");return;}newnode->a = x;newnode->next = NULL;//空队列if (pq->size == 0){pq->_front = newnode;pq->_back = newnode;}else//非空队列{pq->_back->next = newnode;pq->_back = newnode;}pq->size++;
}

五.出队列

队列出数据只能从队头出数据,这样才能保证先进先出规则。而在这里其实就是头删。删除的前提是队列不为空。

头删的时候,我们只需要保存头节点的下一个节点next,然后free掉头节点,再让头节点指向head。

但是这种方式可能会造成野指针。 

当队列只有一个元素的时候,按照这种方式的确会将该节点删除,头节点置为NULL。但是指向尾节点的指针并没有改变指向,也就是说这时候为尾指针成了野指针。等到我们下一次插入数据的话,对尾指针进行解引用就会出错。

所以我们应该判断一下只有一个元素的时候,只有一个元素的时候,直接free掉头节点,然后头指针和尾指针都置为NULL。

删除之后size需要--。

//出队头
void QueuePop(Queue* pq)
{assert(pq);assert(pq->size > 0);//队列不能为空//队列中只有一个元素if (pq->_front == pq->_back){free(pq->_front);pq->_front = NULL;pq->_back = NULL;}else//队列有多个元素{QueueNode* next = pq->_front->next;free(pq->_front);pq->_front = next;}pq->size--;
}

六.获取队头元素

获取队头元素我们直接返回头指针指向节点的数据即可。但是要保证队列不为空。

//获取队头元素
QueueDataType GetQueueFront(Queue* pq)
{assert(pq);assert(pq->size > 0);return pq->_front->a;
}

七.获取队尾元素

获取队尾元素我们直接返回尾指针指向节点的数据即可。同样要保证队列不为空。

//获取队尾元素
QueueDataType GetQueueBack(Queue* pq)
{assert(pq);assert(pq->size > 0);return pq->_back->a;
}

八.获取队列有效元素个数

返回size即可。

//获取队列元素个数
int GetQueueSize(Queue* pq)
{assert(pq);return pq->size;
}

九.判空

判空只需要判断size是否为0即可。

//判空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/874322.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

品牌策划新手指南:如何让你的品牌脱颖而出?

品牌策划,简单来说,就是为品牌制定一套全方位的成长和发展计划,就像给品牌设计一条成长路线图,让它能够更好地吸引顾客、建立信任、提升知名度,最终实现销售和市场份额的增长。 品牌策划是什么? 想象一下…

【前端】JavaScript入门及实战51-55

文章目录 51 函数52 函数的参数53 返回值54 练习55 return 51 函数 <!DOCTYPE html> <html> <head> <title></title> <meta charset "utf-8"> <script type"text/javascript">/* 函数&#xff1a;1. 函数也是…

PCI-X与PCI的优缺点

PCI-X总线改变了PCI总线使用的传送协议。目标设备可以将主设备发送的命令锁存&#xff0c;然后在下一个时钟周期进行译码操作。与PCI总线事务相比&#xff0c;PCI-X总线采用的这种方式&#xff0c;虽然在总线时序中多使用了一个时钟周期&#xff0c;但是可以有效提高PCI-X总线的…

【手撕数据结构】把玩顺序表

目录 顺序表介绍初始化顺序表销毁顺序表打印顺序表增加数据头插尾插指定位置下标插入 删除顺序表元素尾删头删指定位置删除 顺序表介绍 顺序表是⽤⼀段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;⼀般情况下采⽤数组 线性结构又是什么意思&#xff0c;这就…

【性能优化】在大批量数据下使用 HTML+CSS实现走马灯,防止页面卡顿(一)

切换效果 页面结构变化 1.需求背景 项目首页存有一个小的轮播模块,保密原因大概只能这么展示,左侧图片右侧文字,后端一次性返回几百条数据(开发环境下,生产环境只会更多).无法使用分页解决,前端需要懒加载防止页面卡顿 写个小demo演示,如下 2.解决思路 获取到数据后,取第一…

二、链表(2)

24. 两两交换链表中的节点 法一&#xff1a;迭代&#xff0c;while循环&#xff0c;注意要获取next给变量&#xff0c;得先判断非null, 需要4个变量&#xff0c; n0是前&#xff0c;n1 n2是交换的两&#xff0c;n3是n2的下一个可能为空&#xff0c;这种先把变量保存起来&#…

Leetcode1688. 比赛中的配对次数

问题描述&#xff1a; 给你一个整数 n &#xff0c;表示比赛中的队伍数。比赛遵循一种独特的赛制&#xff1a; 如果当前队伍数是 偶数 &#xff0c;那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛&#xff0c;且产生 n / 2 支队伍进入下一轮。如果当前队伍数为 奇…

接口测试总结(非标准)

为什么要做接口测试&#xff1f; 答&#xff1a;接口测试是为了检测系统组件间接口的正确性和稳定性&#xff0c;以及检查数据的交换、传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。接口测试可以帮助我们发现系统中的潜在问题&#xff0c;确保系统的稳定性…

CSP-J模拟赛day1

yjq的吉祥数 文件读写 输入文件 a v o i d . i n avoid.in avoid.in 输出文件 a v o i d . o u t avoid.out avoid.out 限制 1000ms 512MB 题目描述 众所周知&#xff0c; 这个数字在有些时候不是很吉利&#xff0c;因为它谐音为 “散” 所以yjq认为只要是 的整数次幂的数…

JavaWeb连接(JDBC)数据库实现增删改查

JavaWeb连接(JDBC)数据库实现增删改查 1、数据库结构 (1)、创建数据库&#xff08;source_db&#xff09; (2)、创建数据表&#xff08;tb_source&#xff09;&#xff0c;结构如下 字段名说明字段类型长度备注id编号int主键&#xff0c;自增&#xff0c;增量为 1name名称v…

前端面试 vue 按钮级的权限控制

方案一 按钮权限也可以用v-if判断 但是如果页面过多&#xff0c;每个页面页面都要获取用户权限role和路由表里的meta.btnPermissions&#xff0c;然后再做判断 这种方式就不展开举例了 方案二 使用自定义指令实现 按钮级的权限控制 思维导图 心就是自定义指令的书写 首先…

【算法】TopK问题超详解

TopK算法 TopK问题基本框架就是&#xff1a; 从n个数中&#xff0c;找出最大&#xff08;或最小&#xff09;的前k个数。 在我们生活中&#xff0c;经常会遇到TopK问题 比如大众点评的必吃榜&#xff1b;成绩单的前十名&#xff1b;各种数据的最值筛选&#xff1b; [外链图片…

【人工智能】Transformers之Pipeline(四):零样本音频分类(zero-shot-audio-classification)

​​​​​​​ 目录 一、引言 二、零样本音频分类&#xff08;zero-shot-audio-classification&#xff09; 2.1 概述 2.2 意义 2.3 应用场景 2.4 pipeline参数 2.4.1 pipeline对象实例化参数​​​​​​​ 2.4.2 pipeline对象使用参数 2.4 pipeline实战 2.5 模…

【MySQL】:对库和表的基本操作方法

数据库使用的介绍 什么是SQL 学习数据库的使用——>基于 SQL编程语言 来对数据库进行操作 重点表述的是“需求”&#xff0c;期望得到什么结果。&#xff08;至于结果是如何得到的&#xff0c;并不关键&#xff0c;都是数据库服务器在背后做好了&#xff09; 重点表述的是…

线程之间的通信

第一题 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <dirent.h> #include <…

蔡司小乐圆:护航青少年视力健康,专业应对近视挑战

在科技日新月异的今天&#xff0c;电子产品已深度融入青少年的日常&#xff0c;为生活带来便利的同时&#xff0c;也悄然间对他们的视力构成了威胁。近视&#xff0c;这一日益严峻的健康问题&#xff0c;正牵动着无数家庭的心弦。蔡司眼镜&#xff0c;作为眼镜行业的领军者&…

7月21日,贪心练习

大家好呀&#xff0c;今天带来一些贪心算法的应用解题、 一&#xff0c;柠檬水找零 . - 力扣&#xff08;LeetCode&#xff09; 解析&#xff1a; 本题的贪心体现在对于20美元的处理上&#xff0c;我们总是优先把功能较少的10元作为找零&#xff0c;这样可以让5元用处更大 …

代码随想录算法训练营第35天|LeetCode 01背包问题 二维、01背包问题 一维、416. 分割等和子集

1. LeetCode 01背包问题 二维 题目链接&#xff1a;https://kamacoder.com/problempage.php?pid1046 文章链接&#xff1a;https://programmercarl.com/背包理论基础01背包-1.html#算法公开课 视频链接&#xff1a;https://www.bilibili.com/video/BV1cg411g7Y6/ 思路&#xf…

面向对象三大特征及其优劣接口的特点、抽象类的特点

简单介绍下面向对象三大特征&#xff1f; 封装&#xff1a;封装指的就是把对象的属性隐藏在内部&#xff0c;不允许外部对象直接访问内部信息&#xff0c;但是可以提供一些被外界访问的方法来访问属性。优点在于数据隐藏&#xff08;通过定义私有属性&#xff0c;避免直接访问…

JavaScript银行卡实名核验接口集成 代码详解

银行卡实名核验接口是一种用于验证银行卡持有人身份的服务&#xff0c;通常应用于金融机构或第三方支付平台。这种接口允许应用程序或服务发送请求&#xff0c;以验证银行卡所有者的身份信息是否与银行记录相匹配。 应对市场发展需求&#xff0c;翔云提供了银行卡实名认证接口…