算法通过村第六关-树青铜笔记|中序后序

news2024/10/5 15:02:52

文章目录

  • 前言
  • 1. 树的常见概念
  • 2. 树的性质
  • 3. 树的定义与存储方式
  • 4. 树的遍历方式
  • 5. 通过序列构建二叉树
    • 5.1 前中序列恢复二叉树
    • 5.2 中后序列恢复二叉树
  • 总结


前言


提示:瑞秋是个小甜心,她只喜欢被爱,不懂的去爱人。 --几米《你们 我们 他们》

树是一种非常重要的数据结构,在算法和工程中都有大量的应用,我们这里从概念一步一步学习,闯过这一关,掌握树的基本特征以及遍历方面的基础问题。

1. 树的常见概念

树是一个有n个有限节点组成一个具有层次关系的集合,每个节点有0个或者多个子节点,没有父节点的节点为称为根节点,也就是说除了根节点以为每个节点都有父节点,并且有且只有一个节点。树的种类有很多,最常见的就是二叉树了,基本结构如下:

在这里插入图片描述
参考上面图的结构,可以很方面的理解树的概念:

  1. 节点的度:一个节点含有的几点的个数称为该节点的度
  2. 树的度:一颗树中,最大的节点的度称为树的度,注意与节点度的区别
  3. 叶节点或者终端节点:度为0的节点称为叶节点
  4. 非终端节点或者分支节点:度不为0的节点
  5. 双亲节点或者父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点
  6. 孩子节点或者子节点:一个节点含有的子树的根节点称为该节点的子节点
  7. 兄弟节点:具有相同父节点的节点互称为兄弟节点
  8. 节点的祖先:从根节点到该节点所有分支上的所有节点
  9. 子孙:以某节点为根节的子树中任一节点都称为该节点的子孙
  10. 森林:有m(m >= 0 )课互不相交的树的集合称为森林
  11. 无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树
  12. 有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树
  13. 二叉树:每个节点最多含有两个子树的树称为二叉树

2. 树的性质

  • 性质1:在二叉树的第i层上至多有2^(i - 1)个节点(i > 0)
  • 性质2:深度为k的二叉树之多有2^k - 1 个节点(k > 0)
  • 性质3:对于任意一颗二叉树,如果其叶节点数为N0,而度数为2的节点总数为N2,则N0 = N2 + 1
  • 性质4:具有n个节点的完全二叉树的深度必为log2(n + 1)
  • 性质5:对完全二叉树,若从上至下,从左至右编号,则编号为i的节点,其左孩子的编号一定是2i,其右孩子必是2i+ 1;其双亲的编号是i/2(i == 1 时为根,除外哈🤣)

满二叉树和完全二叉树是经常晕的问题,我们有必要单独看一下,满二叉树就是如果一棵二叉树只有度为0的节点和度为2的节点,而且度为0的节点在同一层,则这棵二叉树为满二叉树。

在这里插入图片描述

这颗二叉树为满二叉树,也可以说深度为k=4,有2^k -1 = 15个 节点的二叉树。

完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没有填满外,其余每层节点点数都达到最大值,并且最下面一层的节点都集中在该层的最左侧的若干位置。

这个定义,就有些恶心了,估计大部分看了之后还是不懂什么是完全二叉树,看看下面的图:

在这里插入图片描述
前面两棵树的前n-1层都是满的,最后一层所有子节点都集中在左侧区域,而且节点之间不能有间隙。最后一个为什么呢?他有一个节点缺少一个左子节点/

3. 树的定义与存储方式

注意:

这里我们主要看原理,不执行代码,采用伪代码的方式,理解方便一些

定义树的原理和前面讲的链表本质上差不多,只不过多了一个指针,如果是二叉树的化,只要在链表上的定义增加一个指针就可以了:

public class TreeNode{
    int val;
    TreeNode left;
    TreeNode right;
}

这里本质上就是两个引用,分别指向两个位置,为了方便理解,我们称为左孩子和右孩子。如果是N叉树要如何定义呢?其实就是每个节点最多可以有N个节点指向其他位置,这里就不用left和right,我们使用List存储就行了,也就是如下:

// 定义N叉树
public class TreeNode {
    int val;
    List<TreeNode> nodes;
}

那么是否可以采用数组的方式存储二叉树呢?其实就是用数组来存储二叉树的,顺序存储的方式如图:
在这里插入图片描述
用数组来存储二叉树如何遍历呢?如果父节点的数组下标i,那么它的做还是就是 i* 2 + 1,右孩子就是 i * 2 + 2.

但是用链式表示二叉树,更方便我们理解,所以一般也采用链式二叉树。所以大家要知道一点,数组也是可以便是二叉树的。

使用数组存储的最大问题就是可能存在大量的空间浪费。如图上面假设b没有分支,那么数组1 3 4就空着,但是整个数组的大小仍然是7,因此很少使用数组来存储树。

4. 树的遍历方式

我们常见的树的遍历方式,层次遍历和深度优先遍历两种:

  • 深度优先遍历:先往深走,遇到叶子节点再往回走
  • 广度优先遍历:一层一层的去遍历,一层遍历完再访问下一层

这两种遍历方式不仅仅是二叉树,N叉树也是,图结构也有,我们更常见的叫法:广度优先和深度优先,本质上是一回事。深度优先又有前中后三种,避免混淆,我们记住一点:前指的是中间的父节点再遍历中的顺序,只要明白了这一点,前中后序就是指中间节点的位置就可以了。

看如下中间节点的顺序,就可以发现问题,访问中间节点的顺序就是所谓的遍历方式

前序遍历:中左右
中序遍历:左中右
后序遍历:左右中

大家试着画图写一写,看看自己是否真的理解前中后序了。

在这里插入图片描述

后面大量的算法都与这四种(层次,前中后)遍历方式有关,有的题目根据处理角度不同,可以用层次遍历,也可以用一种甚至两种深度优先的方式来实现。

5. 通过序列构建二叉树

前面我们已经介绍了怎么些前中后序的过程,这里我们看一看怎么通过序列来恢复原始二叉树:

前序遍历:中左右 [5 4 1 2 6 7 8]
中序遍历:左中右 [1 4 2 5 7 6 8]
后序遍历:左右中 [1 2 4 7 8 6 5]

5.1 前中序列恢复二叉树

我们先看看如何通过中前序列恢复二叉树:

前序遍历:中左右 [5 4 1 2 6 7 8]
中序遍历:左中右 [1 4 2 5 7 6 8]
  • 第一轮

我们先从前序第一个就是访问根节点,所以根节点是5

中序遍历的特点是根节点的左子树的元素在根节点左侧,右子树的元素都在根节点右侧,从中序遍历序列我们可以划分成如下结构:

前序序列划分:
5 [ 4 1 2 ] [ 6 7 8 ]
中序序列划分:
[ 1 4 2 ] 5 [ 7 6 8 ] 

当然前序序列第一个括号里面的都是左子树的元素,第二个括号一定都是右子树的元素。

那么这里怎么将这两个括号从哪里分开,我们彩照中序的两个数组划分。我们看前序2之前的元素都在第一个括号中,7之后的元素都在第二个数组中,所以这里从2和7之间划分。

由此我们画图表示一下,看下此时的树的结构:

在这里插入图片描述

  • 第二轮:

我们先看两个序列的第一个数组

根据上面的划分方法:

前序序列划分:
4 [ 1 ] [ 2 ] 
中序序列划分:
[ 1 ] 4 [ 2 ] 

此时树的结构为:
在这里插入图片描述

  • 第三轮

我们看两个序列的第二个数组

根据上面的划分方法:

前序序列划分:
6 [ 7 ] [ 8 ] 
中序序列划分:
[ 7 ] 6 [ 8 ] 

此时树的结构为:
在这里插入图片描述
如此就是最终效果了,可以和上面的图对比一下。

5.2 中后序列恢复二叉树

通过中序和后序也能恢复原始序列,唯一不同的是后续的最后一个是根节点,中序的处理上面是一样的过程。

中序遍历:左中右 [1 4 2 5 7 6 8]
后序遍历:左右中 [1 2 4 7 8 6 5]

这里读者可以自行尝试,我这里不做赘述了。


Q&A💡:

那么有疑问了,为什么前序和后序不能恢复二叉树?

前序遍历:中左右 [5 4 1 2 6 7 8]
后序遍历:左右中 [1 2 4 7 8 6 5]

我们看前序和后序,通过前序我们可以知道根节点,通过后序我们也只能知道根节点,那么中间的部分要怎么划分呢?那些元素属于左子树,那些元素属于右子树呢?很显然,我们不得而知,所以用前序和后序不能恢复二叉树。

推荐力扣的题目⭐⭐⭐:

前序和中序造树:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

中序和后序造树:106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)


总结

提示:树的概念,二叉树、完全二叉树、满二叉树,树的恢复,前中后序序列

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

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

相关文章

uni-app 之 表格设置

uni-app 之 表格设置 image.png <view style"padding: 3%; border: #1296db;"><table style"width: 100%; border-collapse: collapse; "><tr style"height: 50px;border: 2px solid;border-color: #F7F7F7;"><td style&qu…

企业架构LNMP学习笔记26

通过Keepalived可以实现主服务器整机不可用&#xff0c;实现VIP的切换。保证用户可以通过VIP进行访问服务。但是实际上&#xff0c;往往不是服务器整机不可用&#xff0c;只是对应的服务或者软件不可用。 比如说&#xff0c;nginx提供的web的服务&#xff0c;nginx进程关闭。 …

什么是JVM常用调优策略?分别有哪些?

目录 一、JVM调优 二、堆内存大小调整 三、垃圾回收器调优 四、线程池调优 一、JVM调优 Java虚拟机&#xff08;JVM&#xff09;的调优主要是为了提高应用程序的性能&#xff0c;包括提高应用程序的响应速度和吞吐量。以下是一些常用的JVM调优策略&#xff1a; 堆内存大小…

【系统设计系列】数据库

系统设计系列初衷 System Design Primer&#xff1a; 英文文档 GitHub - donnemartin/system-design-primer: Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards. 中文版&#xff1a; https://github.com/donnemarti…

8路编码器脉冲计数器或16路DI高速计数器,Modbus RTU模块 YL69-485 可识别正反转

特点&#xff1a; ● 编码器解码转换成标准Modbus RTU协议 ● 可用作编码器计数器或者转速测量 ● 支持8个编码器同时计数&#xff0c;可识别正反转 ● 也可以设置作为16路独立DI高速计数器 ● 编码器计数值支持断电自动保存 ● DI输入和电源之间3000V隔离 ● 通过RS-4…

奇舞周刊第 505 期:实践指南-前端性能提升 270%!

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 实践指南-前端性能提升 270% 当我们疲于开发一个接一个的需求时&#xff0c;很容易忘记去关注网站的性能&#xff0c;到了某一个节点&#xff0c;猛地发现&#xff0c;随着越来越多…

为什么Python在数据分析行业备受欢迎?优势在哪?

在今天的数据驱动世界中&#xff0c;数据分析已经成为各行业的核心工作之一。数据分析的应用场景非常广泛&#xff0c;例如金融、医疗、教育、电商、社交等领域。数据分析师是一种专门从事数据分析的职业&#xff0c;他们需要掌握一定的编程技能和统计知识&#xff0c;以及对数…

JavaScript实现广告倒计时和跳过广告

倒计时和跳过广告 最近打开手机上的app&#xff0c;映入眼帘的都是一个几秒的广告&#xff0c;带有倒计时&#xff0c;当然如果不喜欢的话可以点击跳过&#xff0c;跳过广告其实质应该就是关闭广告。以前用JavaScript做过一个定时关闭的广告&#xff0c;于是把代码完善了一下&…

作为数据分析师,如何能把AI工具和数据分析工作更好的结合?

​ 做为数据分析师&#xff0c;如果能够学会把AI工具应用到实际的数据分析工作当中&#xff0c;可以把一些重复性很强的工作交给AI来完成&#xff0c;这样数据分析师在提升效率的过程中能够去有更多的时间考虑具有创意的工作。 数据分析师&#xff0c;在使用AI工具完成数据分…

Android相机-架构3

目录 引言 1. Android相机的整体架构 2. 相机 HAL 2.1 AIDL相机HAL 2.2 相机 HAL3 功能 3. HAL子系统 3.1 请求 3.2 HAL和相机子系统 3.2.1 相机的管道 3.2.2 使用 Android Camera API 的步骤 3.2.3 HAL 操作摘要 3.3 启动和预期操作顺序 3.3.1 枚举、打开相机设备…

Java(二)数据类型与变量以及运算符

数据类型与变量以及运算符 二、数据类型与变量&#xff08;重要&#xff09;2.数据类型2.1 基本数据类型 1.变量与常量1.1常量&#xff08;字面常量&#xff09;1.2变量数据类型小总结 三、运算符1.运算符号&#xff08;重要&#xff09;1.1计算运算符1.2增量运算符1.3 自增或自…

AUTOSARCAN-Tp协议

目录 一.单帧、首帧、连续帧、流控帧 单帧传输 SF单帧&#xff1a; 多帧传输 FF&#xff08;首帧&#xff09;&#xff1a; CF&#xff08;连续帧&#xff09;&#xff1a; FC&#xff08;流控帧&#xff09;&#xff1a; 一.单帧、首帧、连续帧、流控帧 CAN诊断由发送端…

数据库服务器是什么意思?数据库服务器有哪些?

数据库服务器是什么意思?现在市场上有很多的服务器的类型&#xff0c;比如数据库服务器&#xff0c;但是很多人对数据库服务器是什么意思?数据库服务器有哪些并不是很熟悉&#xff0c;那么&#xff0c;聚名企服为您详解一下。 一&#xff1a;数据库服务器是什么意思 数据库服…

Vue框架--Vue列表渲染(2)

1.列表过滤 所谓的列表过滤其实就是对数据做一个筛选。实现这一个列表过滤代码可以有两种方式来做: 使用watch监视来实现,如下: 使用计算属性conputed实现,代码如下所示:这里适合使用计算属性实现。

ArcGIS 10.7安装教程!

软件介绍&#xff1a;ArcGIS是一款专业的电子地图信息编辑和开发软件&#xff0c;提供一种快速并且使用简单的方式浏览地理信息&#xff0c;无论是2D还是3D的信息。软件内置多种编辑工具&#xff0c;可以轻松的完成地图生产全过程&#xff0c;为地图分析和处理提供了新的解决方…

Java从入门到精通-数组(二)

4.数组的基本操作 数组的基本操作包括遍历数组、填充替换数组元素、对数组进行排序、复制数组以及查询数组中的元素。 • 4.1 遍历数组 遍历数组是访问数组中所有元素的过程&#xff0c;通常使用循环完成。 使用 for 循环遍历数组&#xff1a; int[] numbers {1, 2, 3, 4…

vue 部署到本机IIS 部署 SPA 应用

安装 URL Rewrite Works With: IIS 7, IIS 7.5, IIS 8, IIS 8.5, IIS 10 URL Rewrite : The Official Microsoft IIS Site 目前公司的 Web 项目是 SPA 应用&#xff0c;采用前后端分离开发&#xff0c;所以有时也会倒腾 Vue 框架。 在 Devops 实践中&#xff0c;容器部署成…

C++11新特性④ | 模板类std::function和标准库函数std::bind

目录 1、引言 2、std::function函数模板类 3、std::bind标准库函数 4、std::bind和std::function配合使用 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;https://blog.csdn.net/chenlycly/article/details/12427258…

Kafka集群与消息可靠性

Kafka集群搭建实战 使用两台Linux服务器&#xff1a;一台192.68.10.7 一台192.168.10.8 192.68.10.7 的配置信息修改 192.168.10.8的配置信息修改 Kafka集群原理 成员关系与控制器 控制器其实就是一个broker, 只不过它除了具有一般 broker的功能之外, 还负责分区首领的选举…

如何优化网站SEO(提高排名和流量的3个小知识)

百度百科SEO简介&#xff1a;搜索引擎优化&#xff08;SearchEngineOptimization&#xff09;是指通过对网站内部结构、外部链接以及页面内容等进行调整&#xff0c;从而使其在搜索引擎中排名更靠前&#xff0c;从而带来更多的流量和曝光。SEO是数字营销中的重要一环&#xff0…