数据结构队列的实现

在这里插入图片描述
本章介绍数据结构队列的内容,我们会从队列的定义以及使用和OJ题来了解队列,话不多说,我们来实现吧

队列

1。队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。
我们来看一下下面的这张图,让我们更好的理解它
在这里插入图片描述
我们从队尾入,队头出,只能是这样入栈和出栈

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

那队列的实现我们是用链式结构来实现的,因为用数组下标的话,出栈的时候要往前挪动数据,会更麻烦,这样队列的意义就下降了,所以我们这里用的方法是链式结构。

typedef int QueueDataType;
typedef struct QueueNode
{QueueDataType* next;QueueDataType data;
}QueueNode;typedef struct Queue
{QueueDataType* head;QueueDataType* tail;
}Queue;

这里我们定义的结构体Queue有很大的作用,因为队列不是像单链表那样,队列是有它的特点的,其中最大的一个特点就是入栈只能从尾入,出栈就是头出,所以我们在这里定义head和tail有很大的作用,定义在结构体当中会方便不少,那我们现在继续往下看我们的接口函数吧。

给大家看一下下面实现队列的接口函数,然后我们一步一步的来实现他们

// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QueueDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QueueDataType QueueFront(Queue* q);
// 获取队列队尾元素
QueueDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);

队列的初始化

void QueueInit(Queue* q); 

初始化我们初始的是结构体Queue中的内容

void QueueInit(Queue* q)
{assert(q);q->head = q->tail = NULL;
}

首先要判断传过来的指针是否是为空,然后将头指针和尾指针都置为NULL。

销毁队列

void QueuePush(Queue* q, QueueDataType data)

首先我们要创造一个节点将它放入,创造节点的结构体就是QueueNode,然后我们要更新后面节点中的head和tail,这里大家肯定有疑问,我们竟然是更新指针,那我们应该传指针的地址才能起到作用,一级指针只能改变结构体的内容,那我们在这里传的话,难道不会产生问题吗?答案是不会,我们的结构体中放的就是指针,那我们只需要改变结构体的内容,就是head和tail就行,竟然是这样的话,我们传一个一级指针就可以起到我们的作用,所以传的是一级,那现在我们在插入函数中先创造一个节点,因为只能从队列的尾插入,而且有了这个指针,我们就不需要像单链表那样再去找尾,我们每次插入都会更新尾。

void QueuePush(Queue* q, QueueDataType data)
{assert(q);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = data;newnode->next = NULL;if (q->head == NULL){q->head = q->tail = newnode;}else{q->tail->next = newnode;q->tail = newnode;}
}

有了入栈就有出栈,出栈的话是从我们的队列最开始的地方出队,我们来实现一下吧!

void QueuePop(Queue* q)
{assert(q);assert(!QueueEmpty(q));QueueNode* headnext = q->head->next;free(q->head);q->head = headnext;}
/

这里的空是因为如果我们的队列都是空的话,我们哪里还有数据进行删除呢
所以要先检查一下是不是为空,那接着我们把这个函数也实现一下吧

bool QueueEmpty(Queue* q)
{assert(q);return q->head == NULL;
}

这个很好理解,如果为空就代表一个数也没有,那我们就不能再对队列进行操作了,那再来看我们下面的接口函数吧。

// 获取队列头部元素
QueueDataType QueueFront(Queue* q)
{assert(q);return q->head->data;
}

有头就有尾,希望我们的人生也是
那我再来实现一下取尾的接口吧

QueueDataType QueueBack(Queue* q)
{assert(q);return q->tail->data;
}

我们继续往下走,实现一下我们后面的接口函数,这些基本上都很简单,我就也不再解释了,看代码就能理解的

int QueueSize(Queue* q)
{assert(q);int count = 0;QueueNode* cur = q->head;while (cur){count++;cur = cur->next;}return count;
}

销毁队列

void QueueDestroy(Queue* q)
{while (!QueueEmpty(q)){QueueNode* headnext = q->head->next;free(q->head);q->head = headnext;}}

统计我们队列节点的数量我们遍历一遍就可以实现了,定义一个cur指针进行遍历,那其他的我们也都讲完了,后面分享栈和队列的OJ题给大家,看完之后对队列有了更深的理解

完整代码

#include"Queue.h"// 初始化队列
void QueueInit(Queue* q)
{assert(q);q->head = q->tail = NULL;
}
// 队尾入队列
void QueuePush(Queue* q, QueueDataType data)
{assert(q);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = data;newnode->next = NULL;if (q->head == NULL){q->head = q->tail = newnode;}else{q->tail->next = newnode;q->tail = newnode;}
}
// 队头出队列
void QueuePop(Queue* q)
{assert(q);assert(!QueueEmpty(q));QueueNode* headnext = q->head->next;free(q->head);q->head = headnext;}
// 获取队列头部元素
QueueDataType QueueFront(Queue* q)
{return q->head->data;
}
// 获取队列队尾元素
QueueDataType QueueBack(Queue* q)
{return q->tail->data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{assert(q);int count = 0;QueueNode* cur = q->head;while (cur){count++;cur = cur->next;}return count;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* q)
{assert(q);return q->head == NULL;
}
// 销毁队列
void QueueDestroy(Queue* q)
{while (!QueueEmpty(q)){QueueNode* headnext = q->head->next;free(q->head);q->head = headnext;}}

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int QueueDataType;
typedef struct QueueNode
{QueueDataType* next;QueueDataType data;
}QueueNode;typedef struct Queue
{QueueDataType* head;QueueDataType* tail;
}Queue;// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QueueDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QueueDataType QueueFront(Queue* q);
// 获取队列队尾元素
QueueDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);

今天的分享就到这里了,我们下次再见

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

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

相关文章

代码随想录打卡—day42—【DP】— 8.27 01背包基础

1 01背包基础 背包概述&#xff1a; 1.1 01背包是什么 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 1.2 01背包二维数组 二维数组还…

HLS实现CORDIC算法计算正余弦并上板验证

硬件&#xff1a;ZYNQ7010 软件&#xff1a;MATLAB 2019b、Vivado 2017.4、HLS 2017.4、System Generator 2017.4 1、CORDIC算法计算正余弦 CORDIC算法详细分析网上有很多资料&#xff0c;它的原理是用一系列旋转去逼近目标角度&#xff0c;这一系列旋转的角度为 θ a r c t…

React入门 组件学习笔记

项目页面以组件形式层层搭起来&#xff0c;组件提高复用性&#xff0c;可维护性 目录 一、函数组件 二、类组件 三、 组件的事件绑定 四、获取事件对象 五、事件绑定传递额外参数 六、组件状态 初始化状态 读取状态 修改状态 七、组件-状态修改counter案例 八、this问…

枫叶时代:《超能一家人》喜剧电影引发观众无限笑点

近期&#xff0c;由浙江开心麻花影业有限公司、中国电影股份有限公司和上海阿里巴巴影业有限公司三家公司联合出品的喜剧电影《超能一家人》引起了观众们的热烈关注。这部影片由宋阳导演执导&#xff0c;他曾执导过备受好评的作品《羞羞的铁拳》。时长108分钟的《超能一家人》以…

Linux环境下远程访问SVN服务:SVN内网穿透的详细配置与操作指南

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

Linux: 使用 ssh 连接其他服务器

通过ifconfig 查看要连接的服务器地址&#xff1a; ubuntuubuntu1804-0172:/media/sangfor/vdc$ ssh ubuntu192.168.11.49 输入要连接的服务器密码: ubuntua192.168.1149 s password: 连接服务器成功&#xff1a;

【⑮MySQL | 视图】概述 | 创建 | 查看 | 更新 | 修改 | 删除

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL视图概述 | 创建 | 查看 | 更新 | 修改 | 删除的分享✨ 目录 前言1.视图概述2.创建视图3.查看视图4.更新视图数据5.修改视图6.删除视图总结 1.视图概述 1.1 为什么使用视图&#xff1f; 视图一方面可以帮我们使…

数据结构--树4.2.1(二叉树)

目录 一、二叉树的存储结构 二、二叉树的遍历 一、二叉树的存储结构 顺序存储结构&#xff1a;二叉树的顺序存储结构就是用一维数组存储二叉树中的各个结点&#xff0c;并且结点的存储位置能体现结点之间的逻辑关系。 链式存储结构&#xff1a;二叉树每个结点最多只有两个孩…

密码学学习笔记(二十一):SHA-256与HMAC、NMAC、KMAC

SHA-256 SHA-2是广泛应用的哈希函数&#xff0c;并且有不同的版本&#xff0c;这篇博客主要介绍SHA-256。 SHA-256算法满足了哈希函数的三个安全属性&#xff1a; 抗第一原像性 - 无法根据哈希函数的输出恢复其对应的输入。抗第二原像性 - 给定一个输入和它的哈希值&#xf…

手写数字识别之优化算法:观察Loss下降的情况判断合理的学习率

目录 手写数字识别之优化算法:观察Loss下降的情况判断合理的学习率 前提条件 设置学习率 学习率的主流优化算法 手写数字识别之优化算法:观察Loss下降的情况判断合理的学习率 我们明确了分类任务的损失函数&#xff08;优化目标&#xff09;的相关概念和实现方法&#xff…

开源软件与知识产权:需要注意什么?

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

为Claude的分析内容做准备:提取PDF页面内容的简易应用程序

由于Claude虽然可以分析整个文件&#xff0c;但是对文件的大小以及字数是有限制的&#xff0c;为了将pdf文件分批传入Claude人工智能分析和总结文章内容&#xff0c;才有了这篇博客&#xff1a; 在本篇博客中&#xff0c;我们将介绍一个基于 wxPython 和 PyMuPDF 库编写的简易的…

锐捷PPP协议原理--尚文网络敏姐

PPP 点对点协议 目录 PPP 点对点协议 PPP 简介 PPP协议层介绍&#xff1a; PPP协议工作原理 第一个阶段&#xff1a;LCP协商 第二阶段&#xff1a;身份认证阶段 第三阶段&#xff1a;NCP协商阶段 PPP配置实验 PAP的单向认证&#xff1a; PAP双向认证 CHAP的单向认证&#…

FreeSWITCH 1.10.10 简单图形化界面1 - docker/脚本/ISO镜像安装

FreeSWITCH 1.10.10 简单图形化界面1 - docker/脚本/ISO镜像安装 0. 界面预览1. Docker安装1.1 下载docker镜像1.2 启动docker镜像1.3 登录 2. 脚本安装2.1 下载2.2 安装2.3 登录2.4 卸载程序 3. 镜像安装3.1 下载镜像3.2 安装镜像3.3 登录 0. 界面预览 http://myfs.f3322.net…

基于android的学生公寓后勤系统/学生公寓管理系统APP

摘 要 随着网络科技的发展&#xff0c;移动智能终端逐渐走进人们的视线&#xff0c;相关应用越来越广泛&#xff0c;并在人们的日常生活中扮演着越来越重要的角色。因此&#xff0c;关键应用程序的开发成为影响移动智能终端普及的重要因素&#xff0c;设计并开发实用、方便的应…

Qt --- 自定义提示框 类似QMessagebox

QMessageBox::information(NULL, QString("title"), QString("I am information")); 以下是自定义提示框的代码&#xff0c;有图有真相&#xff01;提示框大部分都采用模态的形式&#xff0c;关于模态也不再多提&#xff01;所以父类为QDialog&#xff0c;…

android系统启动流程之zygote如何创建SystemServer进程

SystemServer:是独立的进程&#xff0c;主要工作是管理服务的&#xff0c;它将启动大约90种服务Services. 它主要承担的职责是为APP的运行提供各种服务&#xff0c;像AMS,WMS这些服务并不是一个独立的进程&#xff0c; 它们其实都是SystemServer进程中需要管理的的众多服务之一…

G. The Morning Star - 思维

分析&#xff1a; 直接暴力就会tle&#xff0c;不知道怎么下手&#xff0c;可以统计八个方向一条线上的所有坐标&#xff0c;这些坐标一定可以放在一起满足&#xff0c;分析都有哪些线&#xff0c;当横坐标相同时会有竖着的一条线都可以&#xff0c;也就是x c&#xff0c;当纵…

go学习之流程控制语句

文章目录 流程控制语句1.顺序控制2.分支控制2.1单分支2.2双分支单分支和双分支的四个题目switch分支结构 3.循环控制for循环控制while 和do...while的实现 4.跳转控制语句breakcontinuegotoreturngotoreturn 流程控制语句 介绍&#xff1a;在程序中&#xff0c;程序运行的流程…

Vue2学习笔记のvuex

目录 vuex1.概念2.何时使用&#xff1f;3.搭建vuex环境4.基本使用5.getters的使用6.四个map方法的使用7.模块化命名空间 hello, 本文是Vue2学习笔记的第5篇&#xff1a;vuex。 vuex 1.概念 在Vue中实现集中式状态&#xff08;数据&#xff09;管理的一个Vue插件&#xff0c;对…