【数据结构】队列(链表模拟队列)

 

学习本章节必须具备 单链表的前置知识,

建议提前学习:点击链接学习:单链表各种功能函数 细节 详解

本章节是学习用 单链表模拟队列

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先 进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一 端称为队头

使用 数组 还是 链表 模拟 队列 结构?

因为需要 模拟队列 先进先出的 特性:队头 只能出,队尾 只能进

若 使用 数组模拟,每次 pop 队头操作,就需要 全部元素向前面移动,时间复杂度为 O(n)

综上,因为需要 考虑位置变化,选择 链表 实现 队列 较优

需要使用 什么类型的 链表模拟队列?

单向

带头 / 不带头 都可以 :因为哨兵位主要用于 双向链表 找尾 ,为了方便删除,这里差别不大

不循环

我们下面实现的 是 单向不带头不循环链表

实际上,单向或双向,循环或不循环,带头或不带头 完全取决于 你自己要实现一个功能的需求,不是说 一定要固定使用 哪一个套 ,需要灵活选择使用

单向链表 实现队列 的链表节点结构体创建:

typedef int QDataType;
typedef struct QueueNode
{QDataType value;            // 节点数据struct QueueNode* next;     // 指向下一个节点
}QNode;

考虑效率,创建 头尾指针结构体

因为 队列需要:队头 push,队尾 pop

涉及到对 链表 的 尾部操作必须意识到:需要先进行 找尾操作,时间复杂度为 O(n)

方案:因为涉及头尾频繁操作:可以 直接 同时定义 头指针 phead 和 尾指针 ptail

技巧:同类型的变量可以封装成一个结构体

因为 phead 和 ptail 是可以不断变化的,每个相关函数都需要同时传递 phead 和 ptail 两个变量

则可以将多个同类型的变量 封装成 一个结构体,方便操作

这样,传递变量时 直接传递一个 结构体的指针就行了

typedef struct Queue
{QNode* phead;QNode* ptail;
}Queue;
// 区别:减少了传递变量的数量,利于协助开发
// void QueuePush(QNode* phead, QNode* ptail);
void QueuePush(Queue* pq);
// void QueuePop(QNode* phead, QNode* ptail);
void QueuePop(Queue* pq);

Push / Pop :入队 和 出队操作

Push 在队尾入队,Pop 在队头出队

void QueuePop(Queue* pq)
{assert(pq);// pop 的删除操作 需要分类讨论:链表节点个数为 0、为 1、为 两个以上// 为 0 :直接判空,退出操作:phead == ptail == NULLassert(pq->phead);    // 头节点为空 就一定代表为空了// 为 1:phead == ptail  但是 phead != NULL 的情况:即一定指向一个节点if (pq->phead == pq->ptail && pq->phead != NULL) {free(pq->phead);pq->phead = pq->ptail = NULL;}else // 为 两个以上:先记录第二个节点,free 掉头节点,更新头节点{QNode* tmp = pq->phead->next;free(pq->phead);pq->phead = tmp;}
}

为什么 ” 头节点为空 或 尾节点为空 就一定代表链表为空了 “?

观察上面代码:有需要 判断链表节点数量的 需求,为了简化代码与优化过程,可以 直接定义一个 size ,放进结构体中,时刻记录 链表节点数量

// 结构体更改:
typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;// 加入 size 后 的 Push 和 Pop 函数
void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);if (pq->size == 1) {free(pq->phead);pq->phead = pq->ptail = NULL;}else if (pq->size >= 2){QNode* next = pq->phead->next;  // 保留下一个free(pq->phead);pq->phead = next;}pq->size--;    // 注意 pop 代表弹出一个节点,数量 - 1
}void QueuePush(Queue* pq, QDataType x)
{assert(pq);// push 前先创建一个新节点QNode* newNode = (QNode*)malloc(sizeof(QNode));if (newNode == NULL) {perror("malloc fail");return;}newNode->value = x;newNode->next = NULL;if (pq->ptail) // 若 ptail != NULL 说明此时链表不为空{pq->ptail->next = newNode; // 旧的尾节点和一个新的点 进行链接pq->ptail = newNode; // 重新更新尾节点}else  // 若链表为空,则 phead 和 ptail 都要 处理{pq->phead = pq->ptail = newNode;}pq->size++;   // 数量++
}

综上所述,最终代码:

Queue.c

#include"Queue.h"// Push 入队,Pop 出队
void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);if (pq->size == 1) {free(pq->phead);pq->phead = pq->ptail = NULL;}else if (pq->size >= 2){QNode* next = pq->phead->next;  // 保留下一个free(pq->phead);pq->phead = next;}pq->size--;    // 注意 pop 代表弹出一个节点,数量 - 1
}void QueuePush(Queue* pq, QDataType x)
{assert(pq);// push 前先创建一个新节点QNode* newNode = (QNode*)malloc(sizeof(QNode));if (newNode == NULL) {perror("malloc fail");return;}newNode->value = x;newNode->next = NULL;if (pq->ptail) // 若 ptail != NULL 说明此时链表不为空{pq->ptail->next = newNode; // 旧的尾节点和一个新的点 进行链接pq->ptail = newNode; // 重新更新尾节点}else  // 若链表为空,则 phead 和 ptail 都要 处理{pq->phead = pq->ptail = newNode;}pq->size++;   // 数量++
}// 初始化
void  QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}// 销毁链表:就是 单链表的 销毁操作
void QueueDestory(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur) {QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;  // 最后别忘了头尾指针置为 NULLpq->size = 0;
}// Front 返回队头元素
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead); // 若链表为空 自然没有头节点;return pq->phead->value;
}// Back 返回队尾元素
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail); // 若链表为空 自然没有尾节点;return pq->ptail->value;
}// Empty 判断是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}// Size 返回节点数量
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}

Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int QDataType;
typedef struct QueueNode
{QDataType value;struct QueueNode* next;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;// 初始化
void  QueueInit(Queue* pq);   // Push 入队,Pop 出队
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);// Front 队头元素,Back 队尾元素
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);// Empty 判断是否为空,Size 返回节点数量
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);// 销毁链表
void QueueDestory(Queue* pq);

Main.c

#include"Queue.h"int main()
{Queue q;   // 创建队列结构体QueueInit(&q); // 初始化:用于初始化链表的头尾节点:phead  /  ptailfor (int i = 1; i <= 5; ++i) {  // 入队列 几个元素: 1 2 3 4 5QueuePush(&q, i); }// 一个个读取队列元素while (!QueueEmpty(&q)){printf("%d ", QueueFront(&q));QueuePop(&q);}QueueDestory(&q);return 0;
}

【若文章有什么错误,欢迎评论区讨论或私信指出】 

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

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

相关文章

javase基础汇总学习

目录 背景步骤宏观微观理论基础用法面向对象数据类型基础语法&#xff08;关于方法&#xff09;try&#xff08;正常的逻辑代码&#xff09;catch&#xff08;这个和异常有关系&#xff09;finally&#xff08;经典面试题&#xff09; 高阶使用序列化泛型注解反射 总结 背景 后…

大型网站系统架构演化实例_3.使用服务集群改善网站并发处理能力

1.使用服务集群改善网站并发处理能力 使用集群是网站解决高并发、海量数据问题的常用手段。当一台服务器的处理能力、存储空间不足时&#xff0c;不要企图去更换更强大的服务器&#xff0c;对大型网站而言&#xff0c;不管多么强大的服务器&#xff0c;对大型网站而言&…

Jenkins 的构建时执行时间问题

我们希望我的项目能够在特定的时间自动执行&#xff0c;我们需要设定一个定时任务。 Jenkins 的定时任务是通过 Cron 任务来实现的&#xff0c;但是由有点不一样。 H/2 * * * * 比如说上面的设置就是每 2 分钟执行一次。 希望每分钟执行一次 Jenkins 的每分钟执行一次的设置…

【AI工具之Prezo如何自动生成PPT操作步骤】

先说优缺点&#xff1a; 最大的优点就是免费&#xff08;但说实话功能和体验方面很弱&#xff09;支持中文提问&#xff08;最好用英文&#xff09;&#xff0c;智能生成图文&#xff08;但是只能生成英文内容&#xff09;可以AI生成图片&#xff0c;图片很精美酷炫&#xff0…

Eureka基础介绍和使用

目录 一.理论基础 二.父项目 2.1 新建父项目 2.2 管理依赖 三.子项目 3.1 新建子项目 3.2 注册中心Server依赖和启动类和配置文件 3.3 生产者Client 依赖和启动类和配置文件 3.5 消费者Custmer依赖和配置类、启动类和配置文件 四.心跳 五.公共资源项目 5.1新建实体…

空心电抗器的matlab建模与性能仿真分析

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 空心电抗器是一种无铁芯的电感元件&#xff0c;主要由一圈或多圈导线绕制在非磁性材料制成的空心圆筒或其他形状的骨架上构成。其工作原理基于法拉第电磁感应定律&#xff0c;…

【计算机组成原理】加法器原理及其优化

苏泽 本专栏纯个人笔记作用 用于记录408 学习的笔记记录&#xff08;敲了两年码实在不习惯手写笔记了&#xff09; 如果能帮助到大家当然最好 但由于是工作后退下来备考 很多说法和想法都会结合实际开发的思想 可能不是那么的纯粹应试哈 希望大家挑选自己喜欢的口味食用…

现代商业中首席人工智能官(CAIO)的角色与影响

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

备战面试K8S

备战面试&&K8S Kubernetes关于DockerDocker的优缺点分析 WebAssemblyWebAssembly与Container比较 CtrCrictlCtr和CriCtl的区别 Pod生命周期PodConditions容器状态Pod容器组成生命周期的流程 Kubelet EFK日志采集工具的优缺点 Kubernetes 容器运行接口 Container Runti…

CTFHub(web SQL注入)

CTFHub技能树 Web-SQL注入 详解_666c6167-CSDN博客 Ctfhub - web -- SQL注入_ctfhub sql注入-CSDN博客 整数型注入 方法一 根据提示输入1&#xff0c; 闭合方式就是 1 &#xff0c;整数型 存在两列&#xff0c;这里已经给出了字段&#xff0c;不需要再order by了 爆出数据库…

yolov7模型输出层预测方法解读

本文从代码的角度分析模型训练阶段输出层的预测包括以下几个方面&#xff1a; 标注数据&#xff08;下文统称targets&#xff09;的正样本分配策略&#xff0c;代码实现位于find_3_positive。候选框的生成&#xff0c;会介绍输出层的预测值、GT、grid、 anchor之间的联系损失函…

算法练习第20天|回溯算法 77.组合问题 257. 二叉树的所有路径

1.什么是回溯算法&#xff1f; 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。其本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出我们想要的答案。 2.为什么要有回溯算法? 那么既然回溯法并不高效为什么还要用它呢&#xff1f; 因为有的问题能暴力…

Hive进阶(2)----HDFS写入数据流程(赋图助君理解)

HDFS写入数据流程 一、写入流程 1、 Client向NameNode发起RPC请求&#xff0c;来确定请求文件block所在的位置&#xff1b; 2、 NameNode会视情况返回文件的部分或者全部block列表&#xff0c;对于每个block&#xff0c;NameNode都会返回含有该block副本的DataNode地址&…

Ubuntu22.04.4 - 网络配置 - 笔记

一、设置固定ip 1、cd /etc/netplan 查看文件夹下的配置文件 我这里叫 00-installer-config.yaml 2、sudo nano /etc/netplan/00-installer-config.yaml 完成配置后&#xff0c;按下Ctrl O保存更改&#xff0c;然后按下Ctrl X退出nano编辑器。 3、sudo netplan apply 4、ip …

前端开发攻略---合并表格单元格,表格内嵌套表格实现手风琴效果。

1、演示 2、思路 1、用传统的 <table></table> 表格标签来实现比较麻烦。因此通过模拟 表格标签 的写法用<div></div>来实现 2、表头和表格列数是相同的&#xff0c;因此可以确定代码结构 <div class"table"><div class"head…

PotPlayer 图像截取

PotPlayer 图像截取 1. PotPlayer2. PotPlayer 下载2.1. PotPlayer 240305 3. 图像截取References 1. PotPlayer http://www.potplayercn.com/ PotPlayer 是 KMPlayer 原作者姜勇囍进入新公司 Daum 之后推出的&#xff0c;继承了 KMPlayer 所有的优点&#xff0c;拥有异常强大…

Flask项目在Pycharm中设置局域网访问

打开PyCharm导入本应用。点击Run标签中的Edit Configurations 其中Target type选择Script path&#xff0c;Target填入本项目中app.py的路径&#xff0c;Additional optional填入--host0.0.0.0(不要有空格)。 再重新运行项目&#xff0c;会观察到除了原本的http://127.0.0.1:50…

【EI会议征稿通知】2024年图像处理、机器学习与模式识别国际学术会议(IPMLP 2024)

2024年图像处理、机器学习与模式识别国际学术会议&#xff08;IPMLP 2024) 2024 International Conference on Image Processing, Machine Learning and Pattern Recognition 重要信息 大会官网&#xff1a;www.ipmlp.net&#xff08;点击参会/投稿/了解会议详情&#xff09;…

【赛题】2024年“华中杯”数模竞赛赛题发布

2024年"华中杯"数学建模网络挑战赛——正式开赛&#xff01;&#xff01;&#xff01; 赛题已发布&#xff0c;后续无偿分享各题的解题思路、参考文献&#xff0c;帮助大家最快时间&#xff0c;选择最适合是自己的赛题。祝大家都能取得一个好成绩&#xff0c;加油&a…

uiautomation、pytest、schedule实现桌面程序自动化(初级)02

一&#xff1a;安装uiAutomation 前置条件:安装python、pycharm 命令行安装 Pip install uiautomation2.0.17 #指定版本 二&#xff1a;安装辅助工具&#xff1a;inspect.exe和、Accessibility Insights For Windows定位元素工具 辅助工具介绍 步骤中提到…