数据结构(C):二叉树前中后序和层序详解及代码实现及深度刨析

目录

🌞0.前言

🚈1.二叉树链式结构的代码是实现

🚈2.二叉树的遍历及代码实现和深度刨析代码

🚝2.1前序遍历

✈️2.1.1前序遍历的理解

✈️2.1.2前序代码的实现

✈️2.1.3前序代码的深度解剖

🚝2.2中序遍历

✈️2.2.1中序遍历的理解

✈️2.2.中序代码的实现

🚝2.3后序遍历

✈️2.3.1后序遍历的理解

✈️2.3.2后序代码的实现

🚈3.层序遍历

🚝 3.1层序遍历的代码实现

🚈4.二叉树学习的相关建议和方法

✍5.结束语


🌞0.前言

言C之言,聊C之识,以C会友,共向远方。各位博友的各位你们好啊,这里是持续分享数据结构知识的小赵同学,今天要分享的数据结构知识是二叉树的前中后序和层序,在这一章,小赵将会向大家展开聊聊二叉树的前中后序和层序的相关知识。✊

🚈1.二叉树链式结构的代码是实现

有了前面几篇博客的加持,我们也算是对于二叉树有了清晰的认识,在这样的情况下,我们就可以尝试用链表去实现我们的二叉树了。

如这样一棵二叉树

我们该如何实现呢,其实实现起来也容易,就是创建每一个节点,然后用手动把他们连起来,其的操作方法和我们之前的链表很像。

typedef int treenode;
typedef struct BTNode
{int x;//本身存储的数据struct BTNode*left;//左孩子struct BTNode* right;//右孩子
}BTNode;BTNode* BuyNode(int a)//生成一个节点
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));//申请一个空间if (newnode == NULL){perror("malloc failed");return;}newnode->left = NULL;//先默认左右孩子为空newnode->right = NULL;newnode->x = a;return newnode;//返回节点
}
BTNode* CreateBT()
{BTNode* node1 = BuyNode(5);//生成需要的节点BTNode* node2 = BuyNode(6);BTNode* node3 = BuyNode(7);BTNode* node4 = BuyNode(1);BTNode* node5 = BuyNode(3);BTNode* node6 = BuyNode(8);BTNode* node7 = BuyNode(5);node1->left = node2;//将节点连起来node1->right = node3;node2->left = node4;node2->right = node5;node3->left = node6;node3->right = node7;return node1;
}
int main()
{BTNode* phead = CreateBT();}

这样我们就可以建立我们的链表了。 

🚈2.二叉树的遍历及代码实现和深度刨析代码

那我们有了一棵树,现在我想遍历这个树的数据怎么办呢?这个时候我们就提出了三种遍历方式叫前中后序遍历。

🚝2.1前序遍历

✈️2.1.1前序遍历的理解

那么前序是怎么遍历的呢?叫根左右,什么叫做根左右呢?就是先遍历一棵树的根部,再遍历这棵树的左子树,左子树遍历完了,再遍历这棵树的右子树。

 那么对于像我们这棵树的遍历顺序是什么呢?如果用前序遍历的话是5613785

相信这个答案很多人会很惊讶,为什么会是这样呢?其实小赵一开始也是这样,但只要一步步弄懂了,就会觉得不难了。

首先我们遍历这棵树的根部就是5,这个大家应该都没问题。

 

那么接下来我们要干嘛要遍历左子树对不对,那我们就进入左子树进行遍历。这个时候的遍历方法其实就是把它的左子树单独看。

 

好了那么我们怎么遍历左子树呢?还是那个方法啊,先遍历根,根是谁,6,那么5之后就是6。然后我们接着遍历这颗树的左子树,又是根开始就是1,那么6之后就是1。下面遍历1的左子树,我们发现1的左子树没了,那接着遍历右子数,我们发现1的右子树也没了,这个时候我们1这棵子树已经遍历完成了。我们发现对于6来说,1的这棵左子树已经遍历完成了,那就遍历6的右子数,也就是3,等到3也遍历完了,那么6的左右子数就遍历完了,对于最上面的5的根来说,它的左子树就遍历完成了,接着去遍历右子数,还是按照我们遍历左子树的方法去进行遍历。

✈️2.1.2前序代码的实现

void PreOrder(BTNode* root)
{if (root==NULL)//看这个节点是否是空节点{return;//是返回}printf("%d", root->x);//遇到根打印PreOrder(root->left);//遍历左子树PreOrder(root->right);//遍历右子树
}

 看到这个代码的,我的头一阵晕,因为我怎么都无法想象一个这么大的遍历最后实现的代码会这么短。我也很难去进入到这个递归代码的里面去找寻原因,后来我发现一个方面是我的对于深层次的递归可能脑子有点记不住前面的递归,还有一个方面就是我不知道这个函数的返回问题。最终我也是在b站,百度上找到了解决这个问题的办法,这个办法就是递归展开图。

✈️2.1.3前序代码的深度解剖

什么叫递归展开图呢?其实就是把隐藏的代码表示出来,因为我们要无数次的重新进入这个函数,那不如就把每一次的递归场景画出来。

这里呢小赵就演示了一下左子树的递归展开图的方式,下面的中序后序也是一样的 

所以下面小赵可能就不再进行这样的演示,大家可以自行操作,这个的操作软件就是我们电脑上都有的画图软件。

大家可以先将我们的代码截屏一下,然后在画图软件里面用ctrl+v就可以出现很多一样的图了。然后自己用上面的工具去操作还是非常好用的。

🚝2.2中序遍历

✈️2.2.1中序遍历的理解

那么中序是怎么遍历的呢?叫左根右,什么叫做左根右呢?相信大家也都猜出来了就是先遍历一棵树的左子树,遍历完了左子树,再遍历这棵树的根,最后遍历右子树。

其实如果前序能理解这个也大差不差,但是这里有一个点要注意其实和上面的前序遍历一样只有访问根才能接触到数据,遍历其实是接触不到的。

例如这个图如果按中序先遍历左树,5就不是第一个。而要遍历5的左子树。

 那么其的访问方式其实和我们之前遍历是很像的,我们一直遍历一棵树的左子树,知道其中一棵的左子树遍历没了,我们就开始访问这棵树的根节点,这个时候对我们这个图来说就是1作为第一个数据

那么我们最后中序遍历的结果其实是1635875

✈️2.2.中序代码的实现

中序代码的实现

void InOrder(BTNode* root)
{if (root == NULL)//看看这个节点是不是空节点{return;}InOrder(root->left);//遍历左子树printf("%d", root->x);//访问根节点InOrder(root->right);//遍历右子树
}

然后这个代码小赵也是非常推荐大家去按照小赵上面的方法去画递归展开图,虽然初期递归展开图很费时间和经历但对于你去理解二叉树的前中后序是绝对非常有帮助的。 

🚝2.3后序遍历

✈️2.3.1后序遍历的理解

后序遍历就是左右根(其实这个时候我们发现记忆前序中序和后序不难只需要想根节点的位置就行。)

 然后按这种方式遍历,我们会发现最上面的5是最后遍历的,其实相对于任何一棵树都是,根是最后遍历的,因为它必须先遍历左子树和右子树才能访问到根节点。’

然后后序遍历的结果是:1368575

✈️2.3.2后序代码的实现

void PostOrder(BTNode* root)
{if (root == NULL)//看看这个节点是不是空节点{return;}PostOrder(root->left);//遍历左子树PostOrder(root->right);//遍历右子树printf("%d", root->x);//访问根节点
}

这个也是一样要画画递归展开图。  

🚈3.层序遍历

之所以把层序遍历拿出来聊,是因为我感觉这个东西和前面的前中后序还是不大一样,正如它的名字所言,它是一层一层遍历的,在实现的方法上也不是我们之前的递归。

层序遍历的具体方式如下:

✈️🚝✈️ 3.1层序遍历的代码实现

 那么层序遍历主要使用的是什么方法呢?其实是我们的队列,为什么使用队列呢?因为使用队列有一个好处就是先进先出,我们可以让我们的根节点先进去,然后根据根节点,插入我们的左子树和右子树,然后把根节点数据打印出来,然后在进入下一个阶段,左子树把下面两个带入,自己出去。

那么按这样的顺序,5出来后6,7就会进入,6出去后,1,3就会进入,然后是7进入,就可以完美的完成我们的遍历任务了。

因为这里要用到队列,所以小赵就先把前面的代码拷了过来,各位想要实现列表可以看看前面的文章数据结构(c):队列  http://t.csdnimg.cn/Px3yF ,小赵在里面已经非常详细地说明了其的实现方法,这里唯一要注意的是要把里面存的数据改成我们的节点。

typedef  BTNode* QDataType;
void LevelOrder(Queue* Qphead, BTNode* BTphead)
{QueuePush(Qphead, BTphead);//将根节插入队列中while (!QueueEmpty(Qphead)){if (BTphead == NULL){return;}QueuePush(Qphead, BTphead->left);//将根节点的左右子数插入队列QueuePush(Qphead, BTphead->right);int data = BTphead->x;//拿到该节点的数据QueuePop(Qphead);//在队列中删除该节点printf("%d", data);//打印节点BTphead = QueueFront(Qphead);//拿到下一个节点}
}
int main()
{BTNode* phead = CreateBT();Queue* head = (Queue*)malloc(sizeof(Queue));QueueInit(head);//初始化队列LevelOrder(head, phead);
}

层序遍历的代码会相对好懂一些。各位也可以进入代码中去研究,想每一步是如何走的。

这里用我们的调试功能就能很清晰的知道自己的代码是如何运行的了。 

🚈4.二叉树学习的相关建议和方法

二叉树的学习对于整个编程的学习非常重要,它联系着后面的红黑二叉树等相关知识,也联系着我们的重要算法dfs,bfs,在这一阶段,我们要不断地去画递归展开图,才能真正理解透彻这一段代码,小赵在后面也会出一些与其相关的联系题帮助大家去理解。

这里小赵也是从网上找来了相关的动态图片去帮助大家理解。

✍5.结束语

好了小赵今天的分享就到这里了,如果大家有什么不明白的地方可以在小赵的下方留言哦,同时如果小赵的博客中有什么地方不对也希望得到大家的指点,谢谢各位家人们的支持。你们的支持是小赵创作的动力,加油。

如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持小赵,如有不足还请指点,方便小赵及时改正,感谢大家支持!!!

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

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

相关文章

计算机网络:数据链路层 - 扩展的以太网

计算机网络:数据链路层 - 扩展的以太网 集线器交换机自学习算法单点故障 集线器 这是以前常见的总线型以太网,他最初使用粗铜轴电缆作为传输媒体,后来演进到使用价格相对便宜的细铜轴电缆。 后来,以太网发展出来了一种使用大规模…

AI菜鸟向前飞 — LangChain系列之十七 - 剖析AgentExecutor

AgentExecutor 顾名思义,Agent执行器,本篇先简单看看LangChain是如何实现的。 先回顾 AI菜鸟向前飞 — LangChain系列之十四 - Agent系列:从现象看机制(上篇) AI菜鸟向前飞 — LangChain系列之十五 - Agent系列&#…

Springboot使用webupload大文件分片上传(包含前后端源码)

Springboot使用webupload大文件分片上传(包含源码) 1. 实现效果1.1 分片上传效果图1.2 分片上传技术介绍 2. 分片上传前端实现2.1 什么是WebUploader?功能特点接口说明事件APIHook 机制 2.2 前端代码实现2.2.1(不推荐)…

计算机组成原理之计算机系统层次结构

目录 计算机系统层次结构 复习提示 1.计算机系统的组成 2.计算机硬件 2.1冯诺依曼机基本思想 2.1.1冯诺依曼计算机的特点 2.2计算机的功能部件 2.2.1MAR 和 MDR 位数的概念和计算 3.计算机软件 3.1系统软件和应用软件 3.2三个级别的语言 3.2.1三种机器语言的特点 3…

★pwn 24.04环境搭建保姆级教程★

★pwn 24.04环境搭建保姆级教程★ 🌸前言🌺Ubuntu 24.04虚拟机🌷VM🌷Ubuntu 24.04镜像 🌺工具🌷可能出现的git clone错误🌷复制粘贴问题🌷攻击🌷编题 🌺美化&…

【AI大模型】Transformers大模型库(五):AutoModel、Model Head及查看模型结构

目录​​​​​​​ 一、引言 二、自动模型类(AutoModel) 2.1 概述 2.2 Model Head(模型头) 2.3 代码示例 三、总结 一、引言 这里的Transformers指的是huggingface开发的大模型库,为huggingface上数以万计的预…

使用 Keras 的 Stable Diffusion 实现高性能文生图

前言 在本文中,我们将使用基于 KerasCV 实现的 [Stable Diffusion] 模型进行图像生成,这是由 stable.ai 开发的文本生成图像的多模态模型。 Stable Diffusion 是一种功能强大的开源的文本到图像生成模型。虽然市场上存在多种开源实现可以让用户根据文本…

【会议征稿,IEEE出版】第三届能源与电力系统国际学术会议 (ICEEPS 2024,7月14-16)

如今,全球能源行业正面临着前所未有的挑战。一方面,加快向清洁、可再生能源转型是遏制能源环境污染问题的最佳途径之一;另一方面,电力系统中新能源发电、人工智能技术、电力电子装备等被广泛应用和期待,以提高能源可持…

transformer - 注意力机制

Transformer 的注意力机制 Transformer 是一种用于自然语言处理任务的模型架构,依赖于注意力机制来实现高效的序列建模。注意力机制允许模型在处理一个位置的表示时,考虑输入序列中所有其他位置的信息,而不仅仅是前面的几个位置。这种机制能…

ATTCK红队评估(五)

环境搭建 靶场拓扑图: 靶机下载地址: 漏洞详情 外网信息收集 确定目标靶机地址: 发现主机192.168.135.150主机是本次攻击的目标地址。探测靶机开放的端口信息: 目标靶机开放了两个端口:80、3306,那没什么意外的话就是…

每天壁纸不重样~下载必应每日图片

下载必应每日图片 必应不知道你用过没有你下载过必应的图片没有你又没搜索过桌面图片你是不是安装过桌面图片软件你是不是为找一个好看的图片下载过很多桌面软件 必应每日图片 必应每天都会有一张不同的风景图片,画质清晰,而且不收费可以下载使用 但…

重生之我要精通JAVA--第八周笔记

文章目录 多线程线程的状态线程池自定义线程池最大并行数多线程小练习 网络编程BS架构优缺点CS架构优缺点三要素IP特殊IP常用的CMD命令 InetAddress类端口号协议UDP协议(重点)UDP三种通信方式 TCP协议(重点)三次握手四次挥手 反射…

sqlmap直接嗦 dnslog注入 sqllibs第8关

dnslog注入是解决注入的时候没有回显的情况,通过dns外带来进行得到我们想要的数据。 我们是用了dns解析的时候会留下记录,这时候就可以看见我们想要的内容。 这个时候我们还要了解unc路径以及一个函数load_file()以及concat来进行注入。看看我的笔记 unc…

sqli-labs 靶场 less-8、9、10 第八关到第十关详解:布尔注入,时间注入

SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它,我们可以学习如何识别和利用不同类型的SQL注入漏洞,并了解如何修复和防范这些漏洞。Less 8 SQLI DUMB SERIES-8判断注入点 当输入id为1时正常显示: 加上单引号就报错了 …

零基础非科班也能掌握的C语言知识19 动态内存管理

动态内存管理 1.为什么要有动态内存分配2.malloc和free2.1 malloc2.2 free 3.calloc和realloc3.1 calloc3.2realloc 4.常见的动态内存的错误4.1对NULL指针的解引用操作4.2对动态开辟空间的越界访问4.3对非动态内存开辟的空间free4.4使用free释放⼀块动态开辟内存的⼀部分4.5对同…

在Anaconda中安装keras-contrib库

文章目录 1. 有git2. 无git2.1 步骤12.2 步骤22.3 步骤3 1. 有git 如果环境里有git,直接运行以下命令: pip install githttps://www.github.com/farizrahman4u/keras-contrib.git2. 无git 2.1 步骤1 打开网址:https://github.com/keras-tea…

Vue3【十四】watchEffect自动监视多个数据实现,不用明确指出监视哪个数据

Vue3【十四】watchEffect自动监视多个数据实现&#xff0c;不用明确指出监视哪个数据 Vue3【十四】watchEffect自动监视多个数据实现&#xff0c;不用明确指出监视哪个数据 进入立即执行一次&#xff0c;并监视数据变化 案例截图 目录结构 代码 Person.vue <template>&…

Java----抽象类和接口

欢迎大家来这次博客-----抽象类和接口。 1.抽象类 1.1 抽象类概念 在Java中我们都是通过类来描述对象&#xff0c;但反过来并不是所有的类都是用来描述对象的。当一个类中没有足够的信息来描述一个具体对象&#xff0c;我们就将该类称为抽象类。 如上图中的Shape类&#xff…

通用Mapper基础学习

一、引入 二、快速入门 1.创建测试数据 2.搭建MyBatis+Spring 开发环境 3.集成Mapper 4.第一个操作 Mapper接口源码介绍: 创建测试类: 三、常见操作

统计信号处理基础 习题解答10-9

题目 某质检员的工作是监控制造出来的电阻阻值。为此他从一批电阻中选取一个并用一个欧姆表来测量它。他知道欧姆表质量较差&#xff0c;它给测量带来了误差&#xff0c;这个误差可以看成是一个的随机变量。为此&#xff0c;质检员取N个独立的测量。另外&#xff0c;他知道阻值…