【数据结构与算法】8.二叉树的基本概念|前序遍历|中序遍历|后序遍历

news2024/10/7 2:25:04

封面

📚博客主页:爱敲代码的小杨.

✨专栏:《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》

❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️

🙏小杨水平有限,欢迎各位大佬指点,相互学习进步!


文章目录

  • 1. 树形结构(了解)
    • 1.1 概念
    • 1.2 概念(重要)
    • 1.3 树的表示形式(了解)
    • 1.4 树的应用
  • 2. 二叉树
    • 2.1 概念
    • 2.2 特殊的二叉树
    • 2.3 二叉树的性质
    • 2.4 二叉树的存储
  • 3. 二叉树的基本操作
    • 3.1 前置说明
    • 3.2 二叉树的遍历
      • 1. 前序遍历
      • 2. 中序遍历
      • 3. 后序遍历

1. 树形结构(了解)

1.1 概念

树是一种非线性的数据结构,它是由n(n>=0)个有限节点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一个倒挂的树,也就是说它是根朝上,而叶子朝下。它具有的特点:

  • 有一个特殊的几点,称为根节点,根节点没有前驱节点
  • 除根节点外,其余节点被分成m(m>0)个互不相交的集合 T1、T2、…、Tm,其中每一个集合Ti(1<=i<=m)又是一颗与类似的字数。每颗子树的根节点有且只有一个前驱,可以有0个或多个后继
  • 树是递归定义的。



【注意】:树形结构中,子树间不能有交集,否则就不是树形结构

1.2 概念(重要)

节点的度:一个节点含有子树的个数称为该节点的度;如下图:A的度为2
树的度:一棵树中,所有的节点度的最大值称为树的度;如下图:树的度为3
叶子节点或终端节点:度为0的节点称为叶子节点;如下图:G、H、I、J、F节点为叶子节点
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;如下图:A是B的父节点
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;如下图:B是A的孩子节点
根节点:一棵树中,没有双亲节点的节点;如下图:A
节点的层次:从根节点定义来,根为第1层,根的子节点为第2层,以此类推
树的高度:树中节点的最大层次;如下图:树的高度为4


树的以下概念只需了解,知道是什么意思即可:
非终端节点或分支节点:度不为0的节点;如下图:B、C、D、E节点为分支节点
兄弟节点:具有相同父节点的节点互称为兄弟节点;如下图:B、C是互为兄弟节点
堂兄弟节点:双亲在同一层的节点互为堂兄弟节点;如下图:D、E是互为堂兄弟节点
节点的祖先:从根到该节点所经分支上的所有节点;如下图:A是所有节点的祖先
子孙:以某个节点为根的子树中任一节点都称为该节点的的子孙。如下图:所有的接地那都是A的子孙
森林:由m(m>=0)棵互不相交的树组成的集合称为森林

1.3 树的表示形式(了解)

树的结构相对线性表就比较复杂了,要存储不是起来就比较麻烦了,实际中树有很多种表示方式,如:双亲表示法,孩子表示法,孩子双亲表示法,孩子兄弟表示法等等。我们这里就简单的了解其中最常用的孩子兄弟表示法

class Node {
    int val; // 树中存储的数据
    Node firstChild; // 第一个孩子引用
    Node nextBrother;// 下一个兄弟引用
}


线性结构与树形结构的对比

线性结构树形结构
第一个数据元素:无前驱根节点:无双亲,唯一
最后一个数据元素:无后继叶节点:无孩子,可以多个
中间元素:一个前驱,一个后继中间节点:一个双亲多个孩子

1.4 树的应用

文件系统管理(目录和文件)

2. 二叉树

2.1 概念

二叉树是n(n>=0)个节点的有限集合,该集合或者空集(空二叉树),或者由一个根节点和两颗互不相交的、分别称为根节点的左子树和右子树的二叉树组成。

从上图可以看出:

  1. 二叉树不存在度大于2的节点
  2. 二叉树的子树有左右之分,因此二叉树是有序树

总结:对于任意的二叉树都是由以下几种情况复合而成的

大自然中的二叉树:

2.2 特殊的二叉树

  1. 满二叉树:一颗二叉树,如果每层的节点数都达到最大值,则这课二叉树就是,满二叉树。也就是说,如果一颗二叉树的层数为K,且节点总数是 2K -1,则它就是满二叉树
  2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有 n 个节点的二叉树,每个节点都与深度为 K 的满二叉树中编号从0至 n-1的节点(从上到下,从左到右,依次存放)——对应时称之为完全二叉树。要注意的是满二叉树是一种特殊的完全二叉树。

2.3 二叉树的性质

  1. 根节点的层数为1,则一颗非空二叉树的第 i 层上最多有 2i-1 (i > 0)个节点
  2. 若只有根节点的二叉树的深度为1,则深度为 k 的二叉树的最大节点数是2k - 1(k >= 0)
  3. 对任何一颗二叉树,如果其叶子节点个数为 n0,度为2的非叶子节点个数为n2,则有n0 = n2 + 1
  4. 具有 n 个节点的完全二叉树的深度 k 为long2(n+1)上取整
  5. 对于具有 n 个节点的完全二叉树,如果按照从上至下、从左至右的顺序对所有节点从0开始编号,则对于序号 i 的节点有:
    • 若 i > 0,双亲序号:(i - 1) / 2;i = 0,i为根节点编号,无双亲节点
    • 若 2i + 1 < n,左孩子序号:2i + 1,否则无左孩子
    • 若 2i + 2 < n,右孩子序号:2i + 2,否则无右孩子

2.4 二叉树的存储

二叉树的存储结构分为:顺序存储类似于链表的链式存储
二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方法有孩子表示法和孩子双亲表示法,具体如下:

// 孩子表示法
class Node {
   int val;// 数据域
   Node left;// 左孩子的引用,常常代表左孩子为根的整棵左子树
   Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}
// 孩子双亲表示法
class Node {
   int val;// 数据域
   Node left;// 左孩子的引用,常常代表左孩子为根的整棵左子树
   Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
   Node parent;    // 当前节点的根节点
}

3. 二叉树的基本操作

3.1 前置说明

在学习二叉树的基本操作前,需要先创建一颗二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树的结构掌握还不够深入,为了降低学习成本,此处手动创建一颗二叉树,快速进入二叉树的学习。

public class BinaryTree {
    // 节点类
    static class TreeNode{
        public char val;
        public TreeNode left; // 左节点
        public TreeNode right; // 右节点

        // 构造方法
        public TreeNode(char val) {
            this.val = val;
        }
    }

    // 以穷举的方式 创建一颗二叉树
    public TreeNode createTree() {
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');

        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        E.right = H;
        C.left = F;
        C.right = G;
        return A; // 返回根节点
    }
}

注意:上诉代码并不是创建二叉树的方式。
回顾一下二叉树的概念:

  1. 空树
  2. 非空:根节点,根节点的左子树、根节点的右子树组成的

从概念可以看出:二叉树的定义是递归式的,因此后续的基本操作中都是按照该概念实现的。

3.2 二叉树的遍历

学习二叉树的结构,最简单的方式就是遍历,所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题(比如:打印节点内容、节点内容加1)。 遍历是二叉树上最重要的操作之一,是二叉树上进行其它运算之基础。

1. 前序遍历

前序遍历的顺序: 根节点-> 左子树 -> 右子树
遍历演示 :
1713939974206.gif
代码 :

// 前序遍历
void preOrder(TreeNode root) {
	// 判断是否为空树
	if (root == null) {
		return;
	}
	// 打印当前节点的值
	System.out.print(root.val + " ");
	// 递归左子树
	preOrder(root.left);
	// 递归右子树
	preOrder(root.right);
}

2. 中序遍历

中序遍历的顺序: 左子树 -> 根结点 -> 右子树
遍历演示:
1713941722638.gif
代码 :

// 中序遍历
void inOrder(TreeNode root) {
	if (root == null) {
		return;
	}
	// 递归左子树
	inOrder(root.left);
	// 打印当前节点的值
	System.out.print(root.val + " ");
	// 递归右子树
	inOrder(root.right);
}

3. 后序遍历

后序遍历的顺序: 左子树 -> 右子树 -> 根结点
1713941722638.gif
代码:

// 后序遍历
void postOrder(TreeNode root) {
	if (root == null) {
		return;
	}
	// 递归左子树
	postOrder(root.left);
	// 递归右子树
	postOrder(root.right);
	// 打印当前节点的值
	System.out.print(root.val + " ");
}

测试代码:

public class Test {
    public static void main(String[] args) {
        BinaryTree binaryTree = new BinaryTree();
        BinaryTree.TreeNode root = binaryTree.createTree();

        System.out.print("前序遍历:");
        binaryTree.preOrder(root);

        System.out.println();

        System.out.print("中序遍历:");
        binaryTree.inOrder(root);

        System.out.println();

        System.out.print("后序遍历:");
        binaryTree.postOrder(root);
    }
}

运行结果:
image.png

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

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

相关文章

【Linux】iptables的应用

iptables 防火墙 防火墙是一种网络安全系统&#xff0c;它位于内部网络与外部网络&#xff08;如互联网&#xff09;之间&#xff0c;通过实施预定义的安全策略来控制网络间的通信。防火墙的主要目标是保护内部网络资源免受未经授权的访问、攻击或潜在威胁&#xff0c;同时允…

经风靡全球的 PHP 为何逐渐失去优势?

TIOBE 编程语言人气指数发布更新&#xff0c;并提出“PHP 的魔力是否正在消散&#xff1f;”的灵魂拷问。今年 4 月&#xff0c;PHP 在 TIOBE 编程语言指数榜上仅位列第 17&#xff0c;“成为其有史以来的最低排位”。 暴露 PHP 人气急剧下滑的还不只是 TIOBE 榜单。在年度 Sta…

到底什么是爬虫

1. 引言 在数据驱动的世界里&#xff0c;网络爬虫&#xff08;Web Crawling&#xff09;技术扮演着获取和处理网上数据的关键角色。无论是为了数据分析、机器学习项目的数据集构建还是简单地监测网页变化&#xff0c;学习如何创建一个基本的网页爬虫可以大大提升你的工作效率和…

JAVASE基础语法(异常、常用类)

一、异常 1.1 什么是异常 异常就是指不正常。是指代码在运行过程中可能发生错误&#xff0c;导致程序无法正常运行。 package com.atguigu.exception;public class TestException {public static void main(String[] args) {int[] arr {1,2,3,4,5};System.out.println(&quo…

【c++】探究C++中的list:精彩的接口与仿真实现解密

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章来到list有关部分&#xff0c;这一部分函数与前面的类似&#xff0c;我们简单讲解&#xff0c;重难点在模拟实现时的迭代器有关实现 目录 1.List介绍2.接…

CSS3新增特性(二)

四、2D 转换 • 属性名&#xff1a;transform &#xff08;可用于制作2D转换&#xff0c;也可用于制作3D转转换&#xff1b;2D转换是平面上的转换&#xff0c;3D转换是在三维立体空间的转换&#xff09; • 作用&#xff1a;对元素进行水平或垂直方向的移动、缩放、旋转、拉长…

你们项目日志是如何处理的???

ELK日志采集系统 1.什么是ELK ELK 是一套流行的数据搜索、分析和可视化解决方案&#xff0c;由三个开源项目组成&#xff0c;每个项目的首字母合起来形成了“ELK”这一术语&#xff1a; Elasticsearch (ES): Elasticsearch 是一个基于 Apache Lucene 构建的分布式、实时搜索与…

【Python性能优化】list、array与set

list、array与set 详述测试代码 详述 本文对比 list 与 set 在插入和取值时的性能差异&#xff0c;以提供一条什么时候该选择什么数据类型的建议。先上结果&#xff1a; array 与 list 的不同&#xff1a; 内存方面 array 是 C array 的包装&#xff0c;它直接存储数据&#xf…

Vu3+QuaggaJs实现web页面识别条形码

一、什么是QuaggaJs QuaggaJS是一个基于JavaScript的开源图像识别库&#xff0c;可用于识别条形码。 QuaggaJs的作用主要体现在以下几个方面&#xff1a; 实时图像处理与识别&#xff1a;QuaggaJs是一款基于JavaScript的开源库&#xff0c;它允许在Web浏览器中实现实时的图像…

授权协议OAuth 2.0之通过OIDC实现SSO

写在前面 本文来一起看下OIDC&#xff08;openid connect&#xff09;相关内容。 1&#xff1a;什么是OIDC OIDC的全称是openid connect&#xff0c;和OAuth2.0一样&#xff0c;也是属于协议和规范的范畴。OAuth2.0是一种授权协议&#xff0c;即规定了what you can do的内容…

kafka部分partition的leader=-1修复方案整理

kafka部分partition的leader-1修复方案整理 1. 背景说明2. 修复测试2.1 创建正常的topic并验证生产和消费2.2 停止kafka模拟leader-12.3 修复parition2.4 修复完成验证生产消费是否恢复 3. 疑问和思考3.1 kafka在进行数据消费时&#xff0c;如果有partition的leader-1&#xff…

MySQL基础之多表操作(多表查询,事务,索引)

目录 一、多表关系1.1 一对多1.2 外键约束1.3 一对一1.4 多对多 二、多表查询2.1 测试数据准备2.2 笛卡尔积2.3 内连接2.4 外连接2.5 子查询1.标量子查询2.列子查询3.行子查询4.表子查询 三、事务3.1 问题场景引入3.2 概念3.3 事务操作3.4 事务的四大特性ACID 四、索引4.1 概念…

人工智能高速发展 苹果能否赶上AI热潮

近年来&#xff0c;人工智能高速发展&#xff0c;科技大佬们竞相布局人工智能赛道。苹果虽然“晚”了一步&#xff0c;但也在不断追赶这股热潮。随着AI技术不断发展&#xff0c;这项技术已经成为手机发展的新风向标&#xff0c;甚至2024年被视为AI手机元年。 众多手机厂商铆足了…

vue做导入导出excel文档

系统中经常会遇到要实现批量导入/导出数据的功能&#xff0c;导入就需要先下载一个模板&#xff0c;然后在模板文件中填写内容&#xff0c;最后导入模板&#xff0c;导出就可能是下载一个excel文件。 1、导出 新建一个export.js文件如下&#xff1a; import {MessageBox,Mes…

【Xilinx】时序约束学习 TIMING-2: 基准时钟源管脚无效

在错误的管脚 <pin_name> 上创建了基准时钟 <clock_name>。建议仅在适当的时钟根&#xff08;不含时序弧的输入端口或原语输出管脚&#xff09; 上创建基准时钟。 描述 基准时钟必须在时钟树的源时钟上定义。例如&#xff0c; 源时钟可能是设计的输入端口。如果在…

4.20.1 深度神经网络提高放射科医生在乳腺癌筛查中的表现

新颖的两阶段神经网络&#xff0c;用于将全局和局部信息与适当的训练过程结合起来。这使我们能够使用非常高容量的块级网络从像素级标签中学习&#xff0c;同时网络也可以从宏观乳房级标签中学习。模型可以生成可解释的热图&#xff0c;指示可疑发现的位置。即使在拥有大量图像…

Neo4j数据库(二)

目录 WHERE子句 简单WHERE子句语法 复杂WHERE子句语法 DELETE删除 删除节点 DELETE节点子句语法 REMOVE删除 删除节点/关系的属性 REMOVE属性子句语法 SET子句 SET子句语法 WHERE子句 像SQL一样&#xff0c;Neo4j CQL在CQL MATCH命令中提供了WHERE子句来过滤MATCH查询…

VMware-Linux切换桥接模式上网教程(超详细)

这里写目录标题 1. 虚拟机关机2. VMware 虚拟网络配置2.1 检查是否存在 VMnet02.2 修改桥接模式2.3 修改Linux虚拟机网络适配器 3. Linux 系统配置3.1 修改系统网卡配置3.1.1 配置项含义解释3.1.2 查看物理机网络信息3.3.3 修改配置 3.2 重启服务 4. 测试网络连接情况5. 注意事…

Oracle Analytics BIEE 操作方法(四)仪表盘导出“区域”不换行也不合并居中的方法

1 分析 取消所有区域内列格式里面的换行 2 仪表盘 点击“工具” 打印和导出选项 设置固定列宽&#xff08;范围是&#xff1a;0-300&#xff09;

图片像素高效处理,轻松将图片像素进行按比例缩小50%并保存在指定位置,让您的图像更精致!

图像与我们的日常生活紧密相连&#xff0c;从社交媒体分享到专业摄影作品展示&#xff0c;高质量的图片像素处理显得至关重要。然而&#xff0c;面对海量的图片数据和高分辨率的图像处理需求&#xff0c;如何高效、简便地进行像素调整成为了众多用户关注的焦点。 第一步&#…