【队列】数据也得排队

目录

引言

队列的概念

队列的实现

单向链表队列

结构

初始化

入队

出队

取队头

取队尾

求个数

判空

内存释放

总结


引言

队列,这个看似普通的数据结构,其实隐藏着无尽的趣味和巧思。就像单向链表这把神奇的魔法钥匙,它能打开队列的奇妙大门。别担心,这不是一场枯燥的科普,而是一场充满冒险和乐趣的队列解密之旅。跟着我,我们一起揭开队列的神秘面纱,探寻它背后的精彩故事吧!

队列的概念

队列是一种特殊的线性表,它限制了数据的插入操作只能在一端进行,而删除操作则只能在另一端进行。这种先进先出(FIFO,First In First Out)的结构赋予了队列独特的特性。在队列中,进行插入操作的一端被称为队尾,而进行删除操作的一端则被称为队头

队列可以类比为我们在日常生活中经常遇到的排队现象。想象一下你在超市等待结账的队伍,第一个来的人首先被服务,然后是第二个、第三个,以此类推。这就像队列中的先进先出(FIFO)原则,新来的人只能排在队尾,而最先到达的人则首先离开队伍。队列在日常生活中的排队场景中,有效地维持了有序的服务顺序,确保了公平而有序的进行。

队列的实现

队列可以采用数组或链表的结构来实现,其中使用链表结构更为优越。相比数组结构,链表结构的优势在于在队列头部进行出队列操作时,不需要进行元素的搬移(链式结构维护了头指针和尾指针),从而提高了效率。而使用数组结构的话,虽然尾插的效率不错,但是头删的效率就大打折扣了。并且链表结构允许动态地分配和释放内存,更加灵活,适用于处理动态变化的队列大小。因此,使用链表结构实现队列能够更有效地支持队列操作,提升整体性能。

单向链表队列

结构

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>// 定义队列中数据的类型
typedef int QEDataType;// 定义队列节点的结构体
typedef struct QueueNode
{QEDataType* val;         // 数据指针struct QueueNode* next;  // 下一个节点指针
} QueueNode;// 定义队列的结构体
typedef struct Queue
{QueueNode* phead;  // 队头指针QueueNode* ptail;  // 队尾指针int size;          // 队列大小
} Queue;

因为这里我们采用的是单向链表来实现队列,所以在执行入队操作时,时间复杂度会达到O(N),因为需要遍历一次链表来找尾,再进行尾插,所以我们干脆用一个结构体来维护这个队列的头节点和尾节点。并且结构体里还有一个size,这个用来指明队列当前数据个数。然后每个节点存储一个数据指针和下一个节点的指针。这种设计方便了队列的插入和删除操作,同时提供了对队列的基本信息的访问。 

初始化

void QueueInit(Queue* pq)
{assert(pq);  // 确保队列指针不为空pq->phead = NULL;  // 初始化队头指针为空pq->ptail = NULL;  // 初始化队尾指针为空pq->size = 0;      // 初始化队列大小为0
}

初始化队列的操作就好比给队列找了一个“家”,让队列有了一个干净的、什么都没有的地方,以便之后可以安心地往里面添加元素。这个“家”有两个门,一个是队头,一个是队尾。在开始的时候队头和队尾都是空的,还没有元素进来。而整个队列的大小也是零,表示里面一个元素都没有。这样,我们就为队列创造了一个清空的、准备好接纳元素的环境。

入队

void QueuePush(Queue* pq, QEDataType val)
{assert(pq);  // 确保队列指针不为空// 为新元素创建一个队列节点QueueNode* tmp = (QueueNode*)malloc(sizeof(QueueNode));if (tmp == NULL){perror("malloc fail");exit(-1);}tmp->val = val;    // 将新元素的值存入节点tmp->next = NULL;  // 新节点的下一个节点暂时为空pq->size++;        // 队列大小加一if (pq->phead == NULL)  // 如果队列为空,新元素成为队头和队尾{pq->phead = pq->ptail = tmp;}else  // 如果队列不为空,将新元素追加到队尾,并更新队尾指针{pq->ptail->next = tmp;pq->ptail = tmp;}
}

想象一下队列就像是排队等候的人们,每个人都是队列中的一个元素。这个函数的作用就好比是有一个新的人想要加入队伍。我们会为这个人创建一个“队列节点”,这个节点就相当于这个新人的位置,用来存储他的信息。然后,我们检查一下队伍有没有空位如果队伍是空的,这个新人就是队伍的第一位,也是最后一位。如果队伍不是空的,我们就把这个新人加到队尾,然后更新队尾的位置。这样,队伍中就多了一个人,队伍的长度加一。 

出队

void QueuePop(Queue* pq)
{assert(pq);                   // 确保队列指针不为空assert(pq->size > 0);         // 确保队列不为空QueueNode* tmp = pq->phead;   // 临时指针指向队头pq->phead = pq->phead->next;  // 更新队头指针free(tmp);                    // 释放原队头的内存pq->size--;                   // 队列大小减一if (pq->phead == NULL)  // 如果队列变为空,更新队尾指针为空pq->ptail = NULL;
}

首先,我们会找到队头的位置,也就是队伍前面的人,用一个临时指针(tmp)指向这个位置。然后,我们把队头指针往后移动,表示队伍前面的人离开了。接着,我们释放掉原来队头位置的内存,因为这个人已经不在队伍中了。最后,队伍的长度减一,表示队伍中少了一个人。如果队伍变为空,我们还需要把队尾指针更新为空,因为队伍中没有人了,防止出现野指针问题。 

 取队头

QEDataType QueueFront(Queue* pq)
{assert(pq);             // 确保队列指针不为空assert(pq->size > 0);   // 确保队列不为空return pq->phead->val;  // 返回队头元素的值
}

这里通过我们的头指针很轻松就取到了队头的数据。 

取队尾

QEDataType QueueBack(Queue* pq)
{assert(pq);             // 确保队列指针不为空assert(pq->size > 0);   // 确保队列不为空return pq->ptail->val;  // 返回队尾元素的值
}

同理通过尾指针取队尾数据。 

求个数

int QueueSize(Queue* pq)
{assert(pq);       // 确保队列指针不为空return pq->size;  // 返回队列的大小
}

直接返回size的值即可。 

判空

bool QueueEmpty(Queue* pq)
{assert(pq);                // 确保队列指针不为空return pq->ptail == NULL;  // 如果队尾为空,说明队列为空,返回 true,否则返回 false
}

如果队列为空的话,那么尾指针肯定是空,当然头指针也是为空的。 

内存释放

void QueueDestroy(Queue* pq)
{assert(pq);  // 确保队列指针不为空QueueNode* cur = pq->phead;      // 从队头开始遍历队列节点while (cur){QueueNode* tmp = cur->next;  // 保存下一个节点的指针free(cur);                   // 释放当前节点的内存cur = tmp;                   // 移动到下一个节点}pq->phead = pq->ptail = NULL;    // 将队头和队尾指针置为空pq->size = 0;                    // 队列大小清零
}

从队头开始遍历队列中的每个人(节点),释放每个人所占用的位置(内存)。然后,我们把队头和队尾的位置都设置为空,表示队伍不存在了。最后,队伍中的人数也变成了零,因为队伍已经解散了。这样,我们就成功地销毁了队伍,释放了它所占用的一切。 

总结

在这篇博客中,我们一起探索了队列这一数据结构。首先,我们探讨了队列的概念,对它先进先出的特性有了一定程度的了解。接着,我们介绍了队列的实现方式,着重讲解了使用单向链表实现队列的方法。在这一部分,我们探讨了结构设计、初始化、入队、出队、取队头、取队尾、求个数、判空以及内存释放等关键操作,使读者对队列的操作有了基础的了解。希望通过这篇博客,能让读者对队列有更全面的认识,并能够在未来的编程之旅中更加游刃有余地运用队列这一强大的工具。如果你队列的实现对你来说已经不在话下了,可以前往力扣选择队列的题目开冲。

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

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

相关文章

redis数据淘汰策略:

面试官&#xff1a;了解redis数据淘汰策略吗&#xff1f; 就是当Redis内存使用达到设置的上限时&#xff0c; 此时需要使用redis数据淘汰机制来进行数据淘汰。&#xff08;有针对key的 和 针对value数据的&#xff09; Redis支持8种不同策略来选择要删除的key&#xff1a; n…

【JavaSE专栏62】Java继承:面向对象编程中重要的基石

Java继承&#xff1a;面向对象编程中重要的基石 &#x1f680; Java继承&#xff1a;面向对象编程中重要的基石 &#x1f680;摘要引言 &#x1f310; 一、探寻继承的本质 &#x1f575;️‍♂️1. 继承的基本原理2. 实现继承的方式单继承与多继承extends关键字 3. 子类与父类关…

SSL证书更新

首先&#xff0c;我们需要理解为什么需要更新SSL证书。SSL证书的有效期通常为一年。一旦证书过期&#xff0c;浏览器会显示警告&#xff0c;提示用户该网站的SSL证书已经过期&#xff0c;这可能会导致用户对网站的信任度下降&#xff0c;甚至直接离开网站。此外&#xff0c;一些…

【IDEA】IntelliJ IDEA中进行Git版本控制

本篇文章主要记录一下自己在IntelliJ IDEA上使用git的操作&#xff0c;一个新项目如何使用git进行版本控制。文章使用的IDEA版本 IntelliJ IDEA Community Edition 2023.3&#xff0c;远程仓库为https://gitee.com/ 1.配置Git&#xff08;File>Settings&#xff09; 2.去Git…

最新Redis7持久化(权威出版)

首先我们要知道什么是持久化&#xff1a;持久化是指将数据保存到磁盘上&#xff0c;以确保在Redis服务器重启时数据不会丢失。 Redis支持两种主要的持久化方式&#xff1a;RDB持久化和AOF持久化 下面让我依次给你介绍一下&#xff1a; RDB持久化 作用 这是将Redis数据保存…

【JavaSE专栏64】抽象类 vs. 接口:面向对象编程中的非实例化之争

】抽象类 vs. 接口&#xff1a;面向对象编程中的非实例化之争 《抽象类 vs. 接口&#xff1a;面向对象编程中的非实例化之争》摘要 &#x1f680;引言 &#x1f310; 一、抽象类的实质与应用 &#x1f4d8;二、接口&#xff1a;定义规范与实现解耦 &#x1f4dd;三、对比抽象类…

STM32-TIM定时器输出比较

目录 一、输出比较简介 二、PWM简介 三、输出比较通道&#xff08;通用&#xff09; 四、输出比较通道&#xff08;高级&#xff09; 五、输出比较模式 六、PWM基本结构 七、PWM参数计算 八、外设介绍 8.1 舵机 8.2 直流电机及驱动 九、开发步骤 十、输出比较库函数…

组件之间传值

目录 1&#xff1a;组件中的关系 2&#xff1a;父向子传值 3&#xff1a;子组件向父组件共享数据 4&#xff1a;兄弟组件数据共享 1&#xff1a;组件中的关系 在项目中使用到的组件关系最常用两种是&#xff0c;父子关系&#xff0c;兄弟关系 例如A组件使用B组件或者C组件…

以太坊虚拟机EVM介绍,智能合约详解

以太坊为例&#xff1a;什么是智能合约&#xff1f;智能合约怎么部署、调用、执行&#xff1f;智能合约的原理&#xff1f;智能合约存在哪儿&#xff1f;如何区分调用的是智能合约&#xff1f;世界状态数据库、EVM、智能合约它们之间的关系&#xff1f; 什么是智能合约 指的是…

【C语言程序设计】编写简单的C程序

目录 前言 一、程序设计 二、程序改错 三、程序完善 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &#x1f4e3;如…

ubuntu 18.04 pycharm安装

这里主要记录一下ubuntu18.04安装pycharm的过程&#xff0c;以备不时之需查阅~~ 安装并启动 1、通过Other Versions - PyCharm下载相应安装包&#xff0c;并解压。 tar -zxvf pycharm-professoinal-2020.1.3.tar.gz 2、将解压缩后的安装包移动到 /opt 目录下 sudo mv pych…

喜讯:抗HPV全新升级——佳卫苗灭杀病毒HPV正式上市

众所周知&#xff0c;HPV&#xff08;人乳头瘤病毒&#xff09;感染是周多妇科疾病的主要原因&#xff0c;而高危型HPV&#xff08;人乳头瘤病毒&#xff09;的持续感染更是导致宫颈癌的主要因素。自此以后&#xff0c;人类与HPV之间的战斗便从未停止&#xff0c;越来越多的相关…