数据结构-----对列

前言

Hello, 小伙伴们,你们的作者菌又来了,前不久,我们学习了一种数据结构----栈,他特殊的性质使得他在一些数据管理的问题上被广泛的使用,那今天,我们就来学习另一种十分重要的数据结构--对列。

在开始之间,还是按例求三,如果你喜欢我的内容,就请不要忘记,点赞、评论和收藏,你们的支持就是我更新的动力,万分感谢!!

好,我们先在开始。

1.队列的介绍

基本概念:

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

入队列:进行插入操作的一段为队尾;

出队列:进行删除操作的一端称为对头。

队列的底层结构选型:

队列也可以用数组和链表的方式链实现,使用链表的结构实现会更加的优秀,因为如果使用数组的结构,出队列在数组的头部进行,效率会十分底下!! 

2.队列的实现

我门还是先创建三个文件(就向实现其他数据结构一样):

 2.1队列结构的定义:

typedef int QDataType;
typedef struct QueueNode
{QDataType x;struct QueueNode* next;
}QueueNode;typedef struct Queue
{QueueNode* phead;QueueNode* ptail;
}Queue;

怎样来理解这样的定义呢?

队列的定义底层使用的确实是单链表的结构,但是特殊的就是,他只能在头部出数据,只能在为部插入数据,所以,我们可以使用两个结构体,来实现队列:

phead用于出数据;

ptail用于输入数据。

 2.2队列的初始化(QueueIit函数的实现)

2.2.1函数的定义

//初始化队列
void QueueInit(Queue* ps);

2.2.2函数的实现

//初始化队列
void QueueInit(Queue* ps)
{assert(ps);ps->phead = ps->ptail = NULL;
}

初始化的操作与单链表相似。

代码测试:

2.3队列的数据插入(QueuePush函数的实现)

2.3.1 函数的定义

//入队列
void QueuePush(Queue* ps, QDataType  x);

这个也和单链表的结构相似,但是要注意几点,我们先来看函数的是实现代码:

2.3.2函数的实现


QueueNode* BuyNode(QDataType x)
{QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("malloc Fail!!");exit(1);}newnode->x = x;newnode->next = NULL;return newnode;
}
//队列的销毁void QueuePush(Queue* ps, QDataType  x)
{assert(ps);QueueNode* New = BuyNode(x);if (ps->phead == NULL){ps->phead = ps->ptail = New;}else{ps->ptail->next = New;ps->ptail = ps->ptail->next;}
}

1.我们注意不要将QueueNode 和Queue的结构混淆;

2.一定要记得,将新节点的next指针置位NULL;

3.要考虑到ps->phead 和 ps->ptail都为NULL的情况!!

代码测试:

 

入队列的操作就完成了!! 

2.4队列的出数据 (QueuePop函数的实现)

2.4.1函数的定义:

//出队列
void QueuePop(Queue* ps);

2.4.2代码的实现

这里的出队列,其实和单链表的头删是一个逻辑,还是要考虑到一下几点:

1.删除数据的前提是,队列中有元素可删!

2.不能将队列删除为NULL后,任然删除数据!!

bool IsEmpty(Queue* ps)
{return ps->phead == NULL;
}
//IsEmpty函数可以判断队列存储数据的情况
void QueuePop(Queue* ps)
{assert(ps);assert(!IsEmpty(ps));QueueNode* ret = ps->phead->next;free(ps->phead);ps->phead = ret;
}

 代码测试:

2.5取队列的头(尾)数据(QueueTop 函数和 QueueBack函数的实现)

2.5.1函数的定义

//取对头数据
QDataType QueueTop(Queue* ps);
//取队尾数据
QDataType QueueBack(Queue* ps);

这样的操作十分的简单,就和前面我们学习栈的时候,取数据的操作大致相同

2.5.2函数的实现

//取对头数据
QDataType QueueTop(Queue* ps)
{assert(ps && !IsEmpty(ps));return ps->phead->x;
}
//取队尾数据
QDataType QueueBack(Queue* ps)
{assert(ps && !IsEmpty(ps));return ps->ptail->x;
}

 这样的操作十分的简单,我们只需要确保队列中有元素,就可以取出队头和对尾元素。

接下来我们来测试一下,看看能不能达到我们想要的效果:

2.6队列中的数据个数 

在这里,我们可以先写一个函数CountSize来解决这样的问题:

//得出队列中的数据元素个数
int CountSize(Queue* ps);
int CountSize(Queue* ps)
{assert(ps);QueueNode* pcur = ps->phead;int size = 0;while (pcur){size++;pcur = pcur->next;}return size;
}

经过测试,我们可知,这样是可以解决问题的,但是这样做是绝对不规范的!! 

因为队列和栈一样,不能被遍历,也不能被随机的访问!!

同时,如果外界的用户要进行频繁的数据个数获取,我们出于时间复杂度的考虑,因该怎样来修改我们的代码呢? 

所以,我们要怎样才能解决问题呢?

或许,我们在定义队列的节点时,就加上一个元素,来记录我们插入数据的个数

如,这是我们原来的队列定义:

typedef int QDataType;
typedef struct QueueNode
{QDataType x;struct QueueNode* next;
}QueueNode;typedef struct Queue
{QueueNode* phead;QueueNode* ptail;
}Queue;

我们可以修改为

typedef int QDataType;
typedef struct QueueNode
{QDataType x;struct QueueNode* next;
}QueueNode;typedef struct Queue
{QueueNode* phead;QueueNode* ptail;int size;//增加一个元素来记录存储数据的个数!!
}Queue;

每插入一次数据,我们就然size++;

每出一次队列,size--;

在要获取元素个数时,我们只需要,将size返回就行!所以,我们可以来试试这样的方法:

所以CountSize我们可以改写为 

int CountSize(Queue* ps)
{assert(ps);return ps->size;
}

接下来,我们来测试一下:

 

 2.7队列的销毁(QueueDstroy函数的实现)

 2.7.1函数的定义:

void QueueDstroy(Queue* ps);
//队列的销毁

2.7.2函数的实现 

void QueueDestroy(Queue* ps)
{assert(ps && !IsEmpty(ps));QueueNode* ret = ps->phead;while (ret){QueueNode* next = ret->next;free(ret);ret = next;}ps->ptail = ps->phead = NULL;ps->size = 0;
}

销毁的操作和之前链表的操作相似,如果对链表的知识掌握的够好,我们可以直接仿写!!

3.代码展示:

3.1Queu.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int QDataType;
typedef struct QueueNode
{QDataType x;struct QueueNode* next;
}QueueNode;typedef struct Queue
{QueueNode* phead;QueueNode* ptail;int size;}Queue;//初始化队列
void QueueInit(Queue* ps);
//队列的销毁
void QueueDestroy(Queue* ps);
//入队列
void QueuePush(Queue* ps, QDataType  x);
//出队列
void QueuePop(Queue* ps);//取对头数据
QDataType QueueTop(Queue* ps);
//取队尾数据
QDataType QueueBack(Queue* ps);//得出队列中的数据元素个数
int CountSize(Queue* ps);
bool IsEmpty(Queue* ps);

3.2Queue.c

#define _CRT_SECURE_NO_WARNINGS 1#include"Queue.h"//初始化队列
void QueueInit(Queue* ps)
{assert(ps);ps->phead = ps->ptail = NULL;ps->size = 0;
}
void QueueDestroy(Queue* ps)
{assert(ps && !IsEmpty(ps));QueueNode* ret = ps->phead;while (ret){QueueNode* next = ret->next;free(ret);ret = next;}ps->ptail = ps->phead = NULL;ps->size = 0;
}QueueNode* BuyNode(QDataType x)
{QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("malloc Fail!!");exit(1);}newnode->x = x;newnode->next = NULL;return newnode;
}void QueuePush(Queue* ps, QDataType  x)
{assert(ps);QueueNode* New = BuyNode(x);if (ps->phead == NULL){ps->phead = ps->ptail = New;}else{ps->ptail->next = New;ps->ptail = New;}ps->size++;
}
bool IsEmpty(Queue* ps)
{return ps->phead == NULL;
}
void QueuePop(Queue* ps)
{assert(ps);assert(!IsEmpty(ps));QueueNode* ret = ps->phead->next;free(ps->phead);ps->phead = ret;ps->size--;
}
//取对头数据
QDataType QueueTop(Queue* ps)
{assert(ps && !IsEmpty(ps));return ps->phead->x;
}
//取队尾数据
QDataType QueueBack(Queue* ps)
{assert(ps && !IsEmpty(ps));return ps->ptail->x;
}
//得出队列中的数据元素个数
int CountSize(Queue* ps)
{assert(ps);return ps->size;
}

3.3test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
void Test()
{Queue  s;QueueInit(&s);QueuePush(&s, 0);QueuePush(&s, 1);QueuePush(&s, 2);QueuePop(&s);//取对头数据printf("Top:%d\n", QueueTop(&s));//取队尾数据printf("Back:%d\n", QueueBack(&s));printf("Size:%d\n", CountSize(&s));QueueDestroy(&s);printf("Size:%d\n", CountSize(&s));
}int main()
{Test();return 0;
}

好,今天的学习就到这里,我们下期再见,拜拜!!!

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

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

相关文章

Linux字符设备驱动基本框架

本章我们从 Linux 驱动开发中最基础的字符设备驱动开始&#xff0c;重点学习 Linux 下字符设备驱动开发框架。本章会以一个虚拟的设备为例&#xff0c;讲解如何进行字符设备驱动开发&#xff0c;以及如何编写测试 APP 来测试驱动工作是否正常&#xff0c;为以后的学习打下坚实的…

3. 系统上电启动流程

1. 概述 上电启动&#xff0c;可参考恒玄sdk的指导手册。 注&#xff1a;可以在sdk这里加载自己的入口函数 STEP1&#xff1a; STEP2&#xff1a; STEP3&#xff1a; STEP4&#xff1a;

【日常记录】【插件】多媒体文本化: text-image 可以将文字、图片、视频进行「文本化」

文章目录 1. html基本结构2. 画文字3. 画图片4. 画视频参考地址 1. html基本结构 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-s…

ctfshow web入门 中期测评 web492--web502

web492 <?php include(render/render_class.php); include(render/db_class.php);$action$_GET[action]; if(!isset($action)){header(location:index.php?actionlogin);die(); }if($actioncheck){extract($_GET);if(preg_match(/^[A-Za-z0-9]$/, $username)){$sql &qu…

如何设置postgresql数据库的账户密码

说明&#xff1a;在我的云服务器上&#xff0c;postgres是使用yum的方式安装的&#xff0c;不需要设置postgres账户的密码&#xff0c;本文介绍安装后如何手动设置postgres账户的密码&#xff1b; postgres数据库安装&#xff0c;参考下面这篇文章&#xff1a; PostgreSQL安装…

SpringBoot整合SSE技术详解

Hi &#x1f44b;, Im shy SpringBoot整合SSE技术详解 1. 引言 在现代Web应用中,实时通信变得越来越重要。Server-Sent Events (SSE)是一种允许服务器向客户端推送数据的技术,为实现实时更新提供了一种简单而有效的方法。本文将详细介绍如何在SpringBoot中整合SSE,并探讨S…

python-学生排序(赛氪OJ)

[题目描述] 已有 a、b 两个链表&#xff0c;每个链表中的结点包括学号、成绩。要求把两个链表合并&#xff0c;按学号升序排列。输入格式&#xff1a; 输入共 NM1 行。 第一行&#xff0c;输入 a、b 两个链表元素的数量 N、M&#xff0c;中间用空格隔开。下来 N 行&#xff0c;…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十章 Linux用户层和内核层

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

找工作准备刷题Day10 回溯算法 (卡尔41期训练营 7.24)

回溯算法今天这几个题目做过&#xff0c;晚上有面试&#xff0c;今天水一水。 第一题&#xff1a;Leetcode77. 组合 题目描述 解题思路 从题目示例来看&#xff0c;k个数是不能重合的&#xff0c;但是题目没有明确说明这一点。 使用回溯算法解决此问题&#xff0c;利用树形…

ElasticSearch搜索

ES搜索 elastic search 一套搜索引擎技术,主要技术栈包括 Elasticsearch&#xff1a;用于数据存储、计算和搜索 Kibana&#xff1a;用于数据可视化 在数据库模糊查询中,因为不走索引,所以效率很低,而在搜索引擎中,不仅效率高,而且即使出现个别错字,或者用拼音搜索,甚至用同…

docker安装sql server容器

安装 docker pull mcr.microsoft.com/mssql/server:2017-latest启动 docker run -e "ACCEPT_EULAY" -e "SA_PASSWORDwjl135246" -p 1433:1433 -m 4000M --memory 4000M --name sqlserver -d mcr.microsoft.com/mssql/server:2017-latest远程链接即可 参…

用户登录安全是如何保证的?如何保证用户账号、密码安全?

1.HTTP协议直接传输密码&#xff08;无加密&#xff09; 前端 直接发送HTTP请求&#xff08;无加密&#xff09;&#xff0c;攻击者可直接捕获网络包&#xff0c;看到下面的明文信息 因此&#xff0c;使用HTTP协议传输会直接暴露用户敏感信息。 2.HTTPS协议直接传输密码&…

Postgresql 16开启SELINUX

平时我们习惯了&#xff0c;安装数据库&#xff0c;就关闭SELINUX&#xff0c;不关闭SELINUX&#xff0c;就不会安装数据库了&#xff0c;那么不关闭SELINUX&#xff0c;就不能安装数据库了吗&#xff1f; 答案是否定的。 不过&#xff0c;如果我们在开启SELINUX情况下安装PG…

Matlab类阿克曼车机器人运动学演示

v1是后驱动轮轮速&#xff0c; v2是转向角变化速度&#xff0c; 实际上我们只需要关注XQ&#xff0c; YQ和Phi的变化率。 通过这三项和时间步长&#xff0c; 我们就可以计算出变化量&#xff0c; 再结合初始值就能推断出每个时刻的值。 % 清理当前运行环境 % 清除所有变量 cle…

opencv使用KCF算法跟踪目标,给出目标中心位置

效果图 代码 import cv2class VideoTracker:def __init__(self, video_path: str):self.video_path video_pathself.cap cv2.VideoCapture(video_path)self.tracker cv2.legacy.TrackerKCF_create()self.initBB Noneself.tracker_initialized Falseself.selecting Fals…

【教程】vscode添加powershell7终端

win10自带的 powershell 是1.0版本的&#xff0c;太老了&#xff0c;更换为powershell7后&#xff0c;在 vscode 的集成终端中没有显示本篇教程记录在vscode添加powershell7终端的过程 打开vscode终端配置 然后来到这个页面进行设置 查看 powershell7 的安装位置&#xff…

韦东山嵌入式linux系列-异常与中断的概念及处理流程

1 中断的引入 一些概念&#xff1a; 中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运…

数据结构第二讲:顺序表

数据结构第二讲&#xff1a;顺序表 1.线性表2.什么是顺序表3. 静态顺序表4.动态顺序表4.1顺序表基础4.2顺序表的初始化4.3顺序表的销毁4.4顺序表的尾插4.5顺序表的头插4.6顺序表的尾删4.7顺序表的头删4.8顺序表在指定位置之前插入数据4.9顺序表删除指定位置的数据4.10顺序表查找…

JNPF全新V5.0版本!重磅升级——全局优化篇

尊敬的JNPF用户们&#xff1a; 我们非常高兴地宣布&#xff0c;经过团队数月的辛勤努力和不断的技术创新&#xff0c;JNPF快速开发平台终于迎来了里程碑式的全新升级——V5.0版本&#xff01;这一版本的更新发布&#xff0c;不仅代表着我们技术实力的进一步提升&#xff0c;是…

大模型深度神经网络(Deep Neural Network, DNN)

大模型深度神经网络&#xff08;Deep Neural Network, DNN&#xff09;是一种复杂的机器学习模型&#xff0c;其特点在于包含多个隐藏层&#xff0c;从而赋予模型强大的非线性表达能力和对复杂数据模式的学习能力。以下是对大模型DNN的详细介绍&#xff1a; 一、基本概念 深度…