【数据结构】二叉树的前中后序遍历

news2025/7/23 23:48:47

二叉树的三种遍历

  • 1. 创建一棵简单的二叉树
    • 1.1 二叉树结构体实现
    • 1.2 创造一个二叉树结点的函数
    • 1.3 手动创造一棵二叉树
  • 2.为什么要遍历?
  • 3.最重要的知识:由二叉树引出的子问题分析
  • 4.遍历
    • 4.1 前序遍历
    • 4.2 中序遍历
    • 4.3 后序遍历
  • 5.总结

1. 创建一棵简单的二叉树

本篇文章重点讲解关于二叉树的几种遍历,所以手动创建一棵二叉树举例子。

1.1 二叉树结构体实现

typedef int data_type; //把数据类型typedef一下,方便随时更换数据类型

typedef struct BTreeNode
{
	data_type x;     //结点要存储的数据
	struct BTreeNode* left;  //二叉树的左孩子
	struct BTreeNode* right;  // 二叉树的右孩子
}Node;

1.2 创造一个二叉树结点的函数

本篇文章我们要手动创建一棵二叉树来举例子,所以写一个函数方便创造结点,结点创建好后,我们手动连接结点,就可形成二叉树

Node* buyNode(data_type a) //传入结点的数据
{
	Node* node = (Node*)malloc(sizeof(Node)); //创造一个结点
	if (node == NULL) //养成好习惯,判断是否malloc成功
	{
		perror("malloc:");
		exit(-1);
	}
	node->x = a; // 结点的值
	node->left = node->right = NULL; // 结点的左孩子和右孩子都为空
	return node; //返回这个结点
}

1.3 手动创造一棵二叉树

    Node* n1 = buyNode(1); //1是该结点的值,以此类推
	Node* n2 = buyNode(2);
	Node* n3 = buyNode(3);
	Node* n4 = buyNode(4);
	Node* n5 = buyNode(5);
	Node* n6 = buyNode(6);
	Node* n7 = buyNode(7);

	n1->left = n2;  //手动连接,结点n1的左孩子是 n2
	n1->right = n3; // 结点n1的右孩子是 n3
	n2->left = n4; // 结点n2的左孩子是 n4
	n2->right = n5; //结点n2的右孩子是 n5
	n3->left = n6;  //结点n3的左孩子是 n6
	n4->left = n7;  //结点n4的左孩子是 n7

创建的二叉树逻辑图如下:
在这里插入图片描述
我们的二叉树就创建好了,接下来开始用这颗二叉树讲解我们的几种遍历
(实际上创建二叉树并不是这样创建的)

2.为什么要遍历?

我们先来点知识的铺垫:

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:

  1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前,前序遍历又叫深度优先遍历(根-左-右)
  2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。(左-根-右)
  3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。(左-右-根)

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历

3.最重要的知识:由二叉树引出的子问题分析

在这里插入图片描述
为什么二叉树这么好用,引出了各种各样的二叉树。
主要是二叉树可以把一个大树分为一棵课子树,让一棵棵子树去解决问题,最终大树的问题得到解决。
也就说,二叉树把一个问题,转化成了规模更小的子问题,子问题解决了,我们最终的问题也就解决了。这是一个非常重要的思想,算法里随处可见。

注意:二叉树里规模最小的问题是 NULL,而不是最后一个结点。
最后一个结点的子问题是NULL,NULL不可再被分解。

也就是说,我们上图中,实际应该是这样的。
在这里插入图片描述

这点非常重要 切记!!!

4.遍历

4.1 前序遍历

前序遍历就是 先打印根,再打印左子树和右子树。也就是(根-左-右)
注意是,左子树和右子树,子树还能再被分成更小的子树。

先看代码

void preOrder(Node* root)
{
	if (root == NULL) // 如果遇到NULL就直接return返回
	{
	    printf("NULL "); //不打印NULL也可以,我们这里打印,显示最真实的结构
		return;
	}
	printf("%d ", root->x);//遇到根结点就打印
	preOrder(root->left);//递归进左子树
	preOrder(root->right);//递归进右子树
}
preOrder(n1);
//1 2 4 7 NULL NULL NULL 5 NULL NULL 3 6 NULL NULL NULL

来画个图感受一下
在这里插入图片描述
整个过程就形成了这个看起来像大树根一样的图
这就是前序遍历,也叫深度优先遍历
别小看这个过程,这个过程利用递归,完成了从深入到回溯的过程,遍历了整棵树。其思想是以深度为优先,就是每次先走到最底层,走不下来再返回来,走另外一条路。

接下来以代码模拟一下,以下图可能很长,耐心看一下,自己也可以手动像我这样模拟一下,对理解递归有很大的帮助。
因为上面那个图画起来步骤太烦琐,我们这里举这么一棵树模拟一下
这棵树打印结果是:
1 2 NULL NULL 3 NULL NULL
在这里插入图片描述

首先,先解决每一棵左子树,到达NULL后回溯

在这里插入图片描述

然后回溯到结点2后,继续递归进入结点2右子树,右子树也是NULL,直接返回,此时结点2的函数执行完成,直接回到n1调用处

在这里插入图片描述

到这里为止打印了 1 2 NULL NULL,1的右子树交给读者去自行模拟一下吧~

在这里插入图片描述

4.2 中序遍历

中序遍历就是先打印左子树,再打印根,再打印右子树(也就是左-根-右)
整个过程和前序遍历一样可以自行模拟一下。
答案是7 4 2 5 1 6 3 (未打印NULL的情况)

void inOrder(Node* root)
{
	if (root == NULL)
	{
		return;
	}
	inOrder(root->left);
	printf("%d ", root->x);
	inOrder(root->right);
}

4.3 后序遍历

后序遍历就是先打印左子树,再打印右子树,再打印根(也就是左-右-根)
整个过程和前序遍历一样,可以自行模拟一下。
答案是 7 4 5 2 6 3 1 (为打印NULL的情况)

void postOrder(Node* root)
{
	if (root == NULL)
	{
		return;
	}
	postOrder(root->left);
	postOrder(root->right);
	printf("%d ", root->x);
}

5.总结

其实由代码我们可以发现一个规律,printf这个函数位置的规律。
想打印前序遍历,就放在进入左子树和右子树递归前。
想打印中序遍历,就放在中间。
想打印后序遍历,就放在最后。
这个确实是一个很好记忆方法,不过更重要的是知道它的本质。

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

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

相关文章

基于springboot车辆充电桩设计与实现的源码+文档

摘 要 随着信息化时代的到来,管理系统都趋向于智能化、系统化,车辆充电桩管理系统也不例外,但目前国内仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,人工管理显然已无法应对时代的变化&…

18.3 内存池概念、代码实现和详细分析

一:内存池的概念和实现原理概述 malloc:内存浪费,频繁分配小块内存,浪费更加明显。 “内存池”要解决什么问题? 1、减少malloc()的次数,减少malloc()调用次数就意味着减少对内存的浪费 2、减少malloc()的…

JavaEE高阶---SpringBoot的创建和使用

一 : 什么是SpringBoot? Spring的诞生是为了简化 Java 程序的开发的,Spring Boot 的诞生是为了简化 Spring 程序开发的.Spring Boot 是所有基于 Spring 开发的项目的起点 . Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件 . Sprin…

深度学习系列2——Pytorch 图像分类(AlexNet)

1. 概述 本文主要是参照 B 站 UP 主 霹雳吧啦Wz 的视频学习笔记,参考的相关资料在文末参照栏给出,包括实现代码和文中用的一些图片。 整个工程已经上传个人的 github https://github.com/lovewinds13/QYQXDeepLearning ,下载即可直接测试&a…

你了解PMP考试新考纲的内容吗?

2021年新版PMP考纲变化趋势 随着时代发展,PMP认证本身也通过改版不断调整定位,与全球项目管理趋势相匹配,确保在全球项目管理专业领域保持“黄金标准”。 新版本变化如下: 五大过程组变为三大板块。之前一直沿用的“启动、规划…

Transformer时间序列预测

介绍: 提示:Transformer-decoder 总体介绍 本文将介绍一个 Transformer-decoder 架构,用于预测Woodsense提供的湿度时间序列数据集。该项目是先前项目的后续项目,该项目涉及在同一数据集上训练一个简单的 LSTM。人们认为 LSTM 在…

阿里P8总结的Nacos入门笔记,从安装到进阶小白也能轻松学会

前言 都说程序员工资高、待遇好, 2022 金九银十到了,你的小目标是 30K、40K,还是 16薪的 20K?作为一名 Java 开发工程师,当能力可以满足公司业务需求时,拿到超预期的 Offer 并不算难。然而,提升…

GPC规范-SCP02

SPC02 流程 SPC02 指令 命令: 响应: 举例回复: 密钥分散数据: 0000FFFFFFFFFFFFFFFF Key Info: 20 02(scp02) Card挑战数: 001AC6619BE83082 Card加密值: 7…

leetcode刷题(133)——剑指 Offer 07. 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 示例 1: Input: preorder [3,9,20,15,7], inorder [9,3,15,20,7] Output: [3,9,20,null,null,15,7]示例 2: Input: preord…

(十一)笔记.net学习表达式目录树Expression

(十一)笔记.net学习表达式目录树Expression1.什么是表达式目录树(1)Func和表达式的不同(2)表达式树拆解(3)自己拼装表达式目录2.动态拼装表达式目录和扩展应用3.解析表达式目录&…

阿里云服务器采用AMD CPU处理器ECS实例规格详解

阿里云服务器有AMD CPU处理器,阿里云服务器ECS通用型g7a、计算型c7a和内存型r7a采用2.55 GHz主频的AMD EPYCTM MILAN处理器,单核睿频最高3.5 GHz;通用型g6a、计算型c6a和内存型r6a采用2.6 GHz主频的AMD EPYCTM ROME处理器,睿频3.3…

MySQL读取的记录和我想象的不一致——事物隔离级别和MVCC

本篇是《MySQL是怎样运行的》读书笔记,主要分析并发的事务在运行过程中会出现一些可能引发一致性问题的现象。 文章目录1.事务的特性简介1.1 原子性(Atomicity)1.2 隔离性(Isolation)1.3 一致性(Consistenc…

JUC基础

synchronized 复习虚假唤醒什么是虚假唤醒虚假唤醒产生的原因?解决虚假唤醒?Lock接口ReentrantLock 和 synchronized 的区别Lock 实现线程通信Lock 实现线程定制化通信集合线程安全ArrayListHashSetHashMapsynchronized 锁的范围多线程锁公平锁和非公平锁…

CameraMetadata 知识学习整理

一、涉及的相关代码路径 system/media/camera/src/camera_metadata.c // metadata的核心内容,包含metadata内存分配,扩容规则,update, find等 system/media/camera/src/camera_metadata_tag_info.c // 所有android原生tag的在内存里面sect…

22/11/24

1,单调队列; (76条消息) 单调队列专题_Dull丶的博客-CSDN博客 2,kmp算法; 先是自己和自己匹配,求出ne数组,然后和另一串匹配,进行求解; 循环里三步:while&#xff0c…

【Lilishop商城】No2-3.确定软件架构搭建二(本篇包括接口规范、日志处理)

仅涉及后端,全部目录看顶部专栏,代码、文档、接口路径在: 【Lilishop商城】记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客 全篇只介绍重点架构逻辑,具体编写看源代码就行,读起来也不复杂~ 谨慎&#xf…

【数据聚类】基于粒子群、遗传和差分算法实现数据聚类附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

【App自动化测试】(十)特殊控件Toast识别

目录1. toast介绍2. toast定位3. 实例演示前言: 本文为在霍格沃兹测试开发学社中学习到的一些技术写出来分享给大家,希望有志同道合的小伙伴可以一起交流技术,一起进步~ 😘 1. toast介绍 Toast,简易的消息提示框。为了…

CANdelaStudio-从入门到深入目录

前文介绍诊断协议那些事儿专栏,为大家深入介绍了ISO 14229各个服务的基础知识、请求与响应的报文格式,详情可查看:诊断协议那些事儿,从本专题开始,将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希…

HTML5学习笔记(四)

CSS3 颜色样式 在CSS3中,增加了大量定义颜色方面样式的属性,主要包括以下3种。 ▶ opacity透明度 ▶ RGBA颜色 ▶ CSS3渐变 opacity透明度 opacity属性取值是一个数值,取值范围为0.0~1.0。其中0.0表示完全透明,1.0表示完全不透…