队列的实现与讲解

一.概念与结构

1.概念

只允许在⼀端进行插⼊数据操作,在另⼀端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)

入队列:进⾏插⼊操作的⼀端称为队尾

​ 出队列:进⾏删除操作的⼀端称为队头

注意:与上文讲到的栈对比,栈是先进后出,队列是先进先出。

2.结构

队列也可以数组和链表的结构实现,使⽤链表的结构实现更优⼀些,因为如果使⽤数组的结构,出队列在数组头上出数据,效率会⽐较低。

数组头删时间复杂度:O(N) ** 数组尾插时间复杂度:O(1)

单链表头删时间复杂度:O(1) 单链表尾插时间复杂度:O(N)

 因此下午队列的实现中,我们采用链表的结构来进行。

二.队列的实现

queue.h

完整头文件如下。

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int QDataType;
typedef struct QueueNode//队列节点的结构,即单链表节点的结构
{QDataType data;struct QueueNode* next;
}QNode;
typedef struct Queue//队列的结构,定义指向队列头尾的指针,以及队列节点的个数
{QNode* phead;QNode* ptail;QDataType size;
}Q;void QueueInit(Q*);//入队列,队尾
void QueuePush(Q*, QDataType);//出队列,队头
void QueuePop(Q*);//队列判空
bool QueueEmpty(Q*);//取队头数据
QDataType QueueFront(Q*);//取队尾数据
QDataType QueueBack(Q*);//队列有效元素个数
int QueueSize(Q*);void QueueDestroy(Q*);

分析:

1.此处我们定义了两个结构体,一个是队列的基本结构QNode,一个是用来表示队列的队头,队尾和元素个数的Q。

2.Q存在的意义主要是为了便于后续表示队列的队头,队尾时可以简化二级指针的个数,且更加清晰。

test.c

相关测试代码如下。

#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
void QueueTest01()
{Q q;//定义队列QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);///printf("head:%d\n", QueueFront(&q));printf("tail:%d\n", QueueBack(&q));printf("size:%d\n", QueueSize(&q));QueuePop(&q);QueueDestroy(&q);
}int main()
{QueueTest01();return 0;
}

队列的初始化

#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
void QueueInit(Q* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}

分析:

1.需注意,我们此处传入的是指针Q*而非QNode*。

2.其余置空断言操作如常。

队列的销毁

void QueueDestroy(Q* pq)
{assert(pq);assert(!QueueEmpty(pq));QNode* pcur = pq->phead;while (pcur){QNode* next = pcur->next;free(pcur);pcur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}

分析:

1.由于每个节点与之前的链表类似,都是动态开辟的,因此我们通过Q*找到队列头phead,之后逐个释放节点即可。

2.依次释放之后置空并将元素个数置为0即可。

节点的创建

首先创建一个专门用来生产节点的函数,避免后续插入时代码的冗余。

QNode* BuyNode(QDataType x)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = NULL;return newnode;
}

注意:在创建节点后记得把size++。

队尾插入数据——入队列

void QueuePush(Q* pq, QDataType x)
{assert(pq);if (pq->phead == NULL)pq->phead = pq->ptail = BuyNode(x);else{pq->ptail->next = BuyNode(x);pq->ptail = pq->ptail->next;}pq->size++;
}

分析:与链表的尾插原理基本相同。

队列判空

在进入删除之前,首先需要判断队列数据个数是否为空。

bool QueueEmpty(Q* pq)
{assert(pq);return pq->phead == NULL && pq->ptail == NULL;
}

此处通过使用size个数是否为0进行判空也可。

队头删除数据——出队列

void QueuePop(Q* pq)
{assert(pq);assert(!QueueEmpty(pq));//只有一个节点的情况,避免ptail变成野指针if (pq->ptail == pq->phead){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}

分析:

1.首先判断队列数据是否为空。

2.之后考虑两种情况,如果队列只有一个节点,那么直接删除之后需要将队头和队尾都置为空。

3,如果队列不止存在一个节点,同链表的删除原理类似。

返回队头数据

QDataType QueueFront(Q* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->phead->data;
}

返回队尾数据

QDataType QueueBack(Q* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->ptail->data;
}

输出队列数据个数

int QueueSize(Q* pq)
{assert(pq);//不规范且时间复杂度O(n)//int size = 0;//QNode* pcur = pq->phead;//while (pcur)//{//	size++;//	pcur = pcur->next;//}//return size;return pq->size;}

分析:

1.如果我们不在最初引入变量size记录数据个数,由于队列是链表结构无法直接通过下标访问元素个数,需要逐个遍历记录,时间复杂度为O(n)。

2.直接返回size的话就可以减少时间消耗。

三.完整代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
void QueueInit(Q* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}QNode* BuyNode(QDataType x)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = NULL;return newnode;
}void QueuePush(Q* pq, QDataType x)
{assert(pq);if (pq->phead == NULL)pq->phead = pq->ptail = BuyNode(x);else{pq->ptail->next = BuyNode(x);pq->ptail = pq->ptail->next;}pq->size++;
}bool QueueEmpty(Q* pq)
{assert(pq);return pq->phead == NULL && pq->ptail == NULL;
}
void QueuePop(Q* pq)
{assert(pq);assert(!QueueEmpty(pq));//只有一个节点的情况,避免ptail变成野指针if (pq->ptail == pq->phead){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}QDataType QueueFront(Q* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->phead->data;
}QDataType QueueBack(Q* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->ptail->data;
}int QueueSize(Q* pq)
{assert(pq);//不规范且时间复杂度O(n)//int size = 0;//QNode* pcur = pq->phead;//while (pcur)//{//	size++;//	pcur = pcur->next;//}//return size;return pq->size;}void QueueDestroy(Q* pq)
{assert(pq);assert(!QueueEmpty(pq));QNode* pcur = pq->phead;while (pcur){QNode* next = pcur->next;free(pcur);pcur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}

以上就是关于队列的概念,结构和用链表方式实现队列的讲解,欢迎各位大佬前来支持斧正!!!

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

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

相关文章

WebRTC Connection Negotiate解决

最近有个项目 &#xff0c;部署之后一直显示&#xff0c;查了一些资料还是没有解决&#xff0c;无奈只有自己研究解决&#xff1f; 什么是内网穿透&#xff1f; 我们访问我们自己的官网产品页面&#xff0c;我们的服务器是一个单独的个体&#xff0c;有独立的公网ip&#xf…

2024年10月6日历史上的今天大事件早读

23年10月06日西汉“新莽政权”领袖王莽被刺身亡 1866年10月06日清政府批准筹设天津机器局 1905年10月06日俄国爆发铁路工人大罢工 1913年10月06日中、英西姆拉会商“西藏问题” 1927年10月06日阿尔-乔尔森主演第一部有声电影 1940年10月06日新四军获黄桥决战胜利 1949年1…

《迁移学习》—— 将 ResNet18 模型迁移到食物分类项目中

文章目录 一、迁移学习的简单介绍1.迁移学习是什么&#xff1f;2.迁移学习的步骤 二、数据集介绍三、代码实现1. 步骤2.所用到方法介绍的文章链接3. 完整代码 一、迁移学习的简单介绍 1.迁移学习是什么&#xff1f; 迁移学习是指利用已经训练好的模型&#xff0c;在新的任务上…

Windows应急响应-Auto病毒

文章目录 应急背景分析样本开启监控感染病毒查看监控分析病毒行为1.autorun.inf分析2.异常连接3.进程排查4.启动项排查 查杀1.先删掉autorun.inf文件2.使用xuetr杀掉进程3.启动项删除重启排查入侵排查正常流程 应急背景 运维人员准备通过windows共享文档方式为公司员工下发软件…

保险丝基础知识

一、简介 保险丝&#xff08;fuse&#xff09;也被称为电流保险丝&#xff0c;它能够在电流异常升高到一定的高度和热度时&#xff0c;自动熔断切断电流&#xff0c;从而保护电路安全运行。 IEC127标准将它定义为“熔断体&#xff08;fuse-link)”。熔断体是由电阻率比较大而熔…

强化学习笔记之【Q-learning算法和DQN算法】

强化学习笔记&#xff08;一&#xff09;——Q-learning和DQN算法核心公式 文章目录 强化学习笔记&#xff08;一&#xff09;——Q-learning和DQN算法核心公式前言&#xff1a;Q-learning算法DQN算法 前言&#xff1a; 强化学习领域&#xff0c;繁冗复杂的大段代码里面&#…

《软件工程概论》作业一:新冠疫情下软件产品设计

课程说明&#xff1a;《软件工程概论》为浙江科技学院2018级软件工程专业在大二下学期开设的必修课。课程使用《软件工程导论&#xff08;第6版&#xff09;》&#xff08;张海藩等编著&#xff0c;清华大学出版社&#xff09;作为教材。以《软件设计文档国家标准GBT8567-2006》…

【小沐学GIS】blender导入OpenTopography地形数据(BlenderGIS、OSM、Python)

文章目录 1、简介1.1 blender1.2 OpenStreetMap地图 2、BlenderGIS2.1 下载BlenderGIS2.2 安装BlenderGIS2.3 申请opentopography的key2.4 抓取卫星地图2.5 生成高度图2.6 获取OSM数据 结语 1、简介 1.1 blender https://www.blender.org/ Blender 是一款免费的开源 3D 创作套…

IMS添加实体按键流程 - Android14

IMS添加实体按键流程 - Android14 1、实体按键信息&#xff08;Mi 9 左侧实体按键&#xff09;2、硬件添加2.1 内核添加设备节点2.2 Generic.kl映射文件2.3 映射文件文件加载loadKeyMapLocked2.4 addDeviceLocked 添加设备相关对象 3、keycode对应scankode4、KeyEvent.java 添加…

【星汇极客】手把手教学STM32 HAL库+FreeRTOS之创建工程(0)

前言 本人是一名嵌入式学习者&#xff0c;在大学期间也参加了不少的竞赛并获奖&#xff0c;包括但不限于&#xff1a;江苏省电子设计竞赛省一、睿抗机器人国二、中国高校智能机器人国二、嵌入式设计竞赛国三、光电设计竞赛国三、节能减排竞赛国三。 后面会经常写一下博客&…

服务器conda环境安装rpy2

参考博客 https://stackoverflow.com/questions/68936589/how-to-select-r-installation-when-using-rpy2-on-conda 现在我遇到这样一个问题&#xff0c;服务器系统环境没有R(没有权限安装&#xff09;&#xff0c;我只能在minconda的conda环境中使用R, 使用方法如下 我现在…

(11)MATLAB莱斯(Rician)衰落信道仿真2

文章目录 前言一、莱斯衰落信道仿真模型二、仿真代码与结果1.仿真代码2.仿真结果画图 三、后续&#xff1a;四、参考文献&#xff1a; 前言 首先给出莱斯衰落信道仿真模型&#xff0c;该模型由直射路径分量和反射路径分量组成&#xff0c;其中反射路径分量由瑞利衰落信道模型构…

Art. 1 | 信号、信息与消息的区别及其在通信中的应用

信号、信息与消息的区别及其在通信中的应用 通信技术是现代社会的基石&#xff0c;其广泛应用于日常生活的各个方面。从手机、互联网到企业信息管理&#xff0c;通信系统无处不在。在这一技术领域中&#xff0c;信号、信息和消息是三大基础概念&#xff0c;支撑着整个通信系统…

云计算Openstack Glance

OpenStack Glance&#xff08;或称为Glance&#xff0c;但通常OpenStack官方文档中使用的是“Glance”作为项目代号&#xff09;是OpenStack的镜像服务组件&#xff0c;为创建虚拟机提供镜像服务。以下是对OpenStack Glance的详细解析&#xff1a; 一、基本功能 Glance主要提…

【AI人工智能】文心智能体,双人冒险游戏智能体创作分享

背景 最近半年&#xff0c;“AI agent”&#xff08;智能体&#xff09;这一词汇变得非常热门。许多人以为创建自己的智能体会很复杂&#xff0c;实际上&#xff0c;现有的平台已经大大降低了操作门槛。只要有创意&#xff0c;几乎每个人都可以轻松创建属于自己的智能体。今天…

Linux下静态库与动态库制作及分文件编程

Linux下静态库与动态库制作及分文件编程 文章目录 Linux下静态库与动态库制作及分文件编程1.分文件编程1.1优点1.2操作逻辑1.3示例 2.Linux库的概念3.静态库的制作与使用3.1优缺点3.2命名规则3.3制作步骤3.4开始享用 4.动态库的制作与使用4.1优缺点4.2动态库命名规则4.3制作步骤…

Uniapp API

1.uni.showToast 显示消息提示框 unishowToast({ obj参数 }) 2.uni.showLoading 显示 loading 提示框, 需主动调用 uni.hideLoading 才能关闭提示框。 3.uni.showModal 显示模态弹窗&#xff0c;可以只有一个确定按钮&#xff0c;也可以同时有确定和取消按钮。类似于一个A…

VLAN:虚拟局域网

VLAN:虚拟局域网 交换机和路由器协同工作后&#xff0c;将原先的一个广播域&#xff0c;逻辑上&#xff0c;切分为多个广播域。 第一步:创建VLAN [SW1]dispaly vlan 查询vlan VID&#xff08;VLAN ID&#xff09;:用来区分和标定不同的vlan 由12位二进制构成 范围: 0-4…

算法笔记(十一)——优先级队列(堆)

文章目录 最后一块石头的重量数据流中的第 K 大元素前K个高频单词数据流的中位数 优先级队列是一种特殊的队列&#xff0c;元素按照优先级从高到低&#xff08;或从低到高&#xff09;排列&#xff0c;高优先级的元素先出队&#xff0c;可以用 堆来实现 堆是一种二叉树的结构&…

HTB:Preignition[WriteUP]

连接至HTB服务器并启动靶机 靶机IP&#xff1a;10.129.157.49 分配IP&#xff1a;10.10.16.12 1.Directory Brute-forcing is a technique used to check a lot of paths on a web server to find hidden pages. Which is another name for this? (i) Local File Inclusion, (…