数据结构(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.结束语

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【QT5】<总览五> QT多线程、TCP/UDP

文章目录 前言 一、QThread多线程 二、QT中的TCP编程 1. TCP简介 2. 服务端程序编写 3. 客户端程序编写 4. 服务端与客户端测试 三、QT中的UDP编程 1. UDP简介 2. UDP单播与广播程序 前言 承接【QT5】<总览四> QT常见绘图、图表及动画。若存在…

开启数字化校园解决方案,实现教育智能化

现代社会的教育面临诸多挑战,如何提高教育质量,实现教育智能化成为了当务之急。数字化校园解决方案应运而生,为学校提供了全新的教学模式和管理方式。本文将介绍数字化校园解决方案的重要性,以及如何开启数字化校园,实…

【端午安康,给大家讲个“网络”故事,深刻一下!】

牛马我🐴上周又挨锤了, 网络是不稳定的,博学多知的你可能知道,可能不知道。但假如没亲身经历过,知不知道都不深刻,牛马踩了个网络的坑,深刻了,这里分享下, 一个真相 无…

【Python报错】已解决ImportError: cannot import name ‘triu’ from ‘scipy.linalg’

成功解决“ImportError: cannot import name ‘triu’ from ‘scipy.linalg’”错误的全面指南 在Python编程中,尤其是在使用scipy这个科学计算库时,可能会遇到ImportError错误,提示无法从scipy.linalg模块中导入名为triu的函数。这个错误通…

深入JVM:线上内存泄漏问题诊断与处理

文章目录 深入JVM:线上内存泄漏问题诊断与处理一、序言二、内存泄漏概念三、内存泄漏环境模拟四、内存泄漏诊断与解决1、步骤一:获取堆内存快照文件(1)获取正在运行程序dump文件(2)获取已终止程序dump文件 …

HP Laptop 14s-fr1xxx原厂oem预装Win11系统ISO镜像下载

惠普星青春版14s-fr1xxx笔记本电脑原装出厂Windows11系统安装包,恢复出厂开箱状态一模一样 链接:https://pan.baidu.com/s/11Qe5XgCmH3emIVEpvoKclg?pwdm1qe 提取码:m1qe 适用型号:14s-fr1xxx 14s-fr0001AU、14s-fr0002AU、…

VMware Fusion 如何增加linux硬盘空间并成功挂载

文章目录 0. 前言1. 增加硬盘空间2. 硬盘分区2.1 查看硬盘2.2 分区2.3 格式化2.4 挂载 3. 参考 0. 前言 如果发现虚拟机分配的硬盘不足,需要增加硬盘空间。本文教给大家如何增加硬盘空间并成功挂载。 查看当前硬盘使用情况: df -h可以看到&#xff0c…

sqli-labs 靶场 less-7 第七关详解:OUTFILE注入与配置

SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它,我们可以学习如何识别和利用不同类型的SQL注入漏洞,并了解如何修复和防范这些漏洞。Less 7 SQLI DUMB SERIES-7判断注入点 进入页面中,并输入数据查看结果。 发现空数据提…

求宇文玥在水下的浮力和赵丽颖捞他的时间

关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业分析/数据结构与算法学习资料 2024年汉东省在达康书记的带领下率先实现高考试点改革。为让更多的考生能提升对他们的理解和记忆,把电视剧的场景融入考试题目中。确保学生看一遍就懂,想…

debian12安装时分区方案

一、初次尝试 一共设置了4个分区,其中根目录/分区46G,swap分区10G(电脑内存为6G),/boot分区200M,/home分区55G。系统安装之后的实际占有情况为: 二、调整后情况 一共设置了4个分区&#xff0c…

基于R语言BIOMOD2 及机器学习方法的物种分布模拟与案例分析

原文链接:基于R语言BIOMOD2 及机器学习方法的物种分布模拟与案例分析https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247606139&idx4&snf94ec30bfb5fa7ac0320403d49db3b66&chksmfa821e9ccdf5978a44a9ba96f6e04a121c0bbf63beea0940b385011c0b…

Spring运维之boo项目表现层测试匹配响应执行状态响应体JSON和响应头

匹配响应执行状态 我们创建了测试环境 而且发送了虚拟的请求 我们接下来要进行验证 验证请求和预期值是否匹配 MVC结果匹配器 匹配上了 匹配失败 package com.example.demo;import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Auto…

【网络教程】Iptables官方教程-学习笔记7-简单理解IPTABLES规则的作用流程

前面学习了IPTABLES的所有功能介绍后,一个Linux设备里的IPTABLES规则集是如何运行的,这里简单做个介绍。 在Linux设备里输入"iptables -nvl",得到该设备的所有防火墙规则,得到的结果中可以看到这个设备防火墙里所有的链以及链里的…

2024年CKA模拟系统制作 | step-by-step | 1、基础环境准备

目录 一、软件环境 二、虚拟网络环境准备 1、编辑虚拟网络 2、网络设置 三、新建虚拟主机 1、新建目录 2、新建虚拟主机 四、系统安装 1、装载系统镜像 2、开启虚拟机 3、选择语言 4、键盘选择 5、网络配置 6、代理设置 7、设置软件源 8、存储设置 9、名称设置 …

计算机网络 —— 网络层 (路由协议)

计算机网络 —— 网络层 (路由协议) 什么是路由协议内部网关协议RIP关键特性 OSPF主要特点 外部网关协议BGP关键特性 我们今天来看路由协议: 什么是路由协议 路由协议是网络设备(主要是路由器)用来决定数据包在网络中…

【爬虫实战项目一】Python爬取豆瓣电影榜单数据

目录 一、环境准备 二、编写代码 2.1 分页分析 2.2 编码 一、环境准备 安装requests和lxml pip install requests pip install lxml 二、编写代码 2.1 分页分析 编写代码前我们先看看榜单的url 我们假如要爬取五页的数据,那么五个url分别是: htt…

工业互联网数字中台建设方案(ppt原件)

工业互联网数字中台解决方案旨在为企业提供全面、高效的数据驱动能力。该方案主要包括以下几个核心部分: 数据中台:作为核心,数据中台负责汇聚、整合、提纯和加工各类工业数据,实现数据资产的标准化、模型化和模块化。通过提供API…

cmake使用make和Ninja构建对比

前提 make和Ninja是两个常见的构建工具,在网上查阅了一些资料,说是Ninja比make构建速度要快很多。但是具体不知道快多少,所以趁着这次编译clang的机会,分享下它们在时间方面差多少。 步骤 下载llvm 参考llvm官网,这…

linux系统的网络工具和命令非常多,应该如何学习可以快速提高?

目录 一、linux的网络命令有多少? (一)网络配置 (二)网络监控 (三)网络诊断 (四)网络通信 (五)网络文件传输 (六)网…

java web:springboot mysql开发的一套家政预约上门服务系统源码:家政上门服务系统的运行流程

java web:springboot mysql开发的一套家政预约上门服务系统源码:家政上门服务系统的运行流程 家政上门服务系统的优势 服务质量更稳定:由专业的家政人员提供服务,经过严格的培训和筛选。 价格更透明:采用套餐式收费&…