二叉树的构造(如何唯一确定一棵二叉树?附证明)

news2024/12/28 21:01:09

二叉树的构造(如何唯一确定一棵二叉树?附证明)

一些直观的认识

▪ 同一棵二叉树具有唯一先序序列、中序序列和后序序列。

▪ 不同的二叉树可能具有相同的先序序列、中序序列和后序序列。

image-20221210201231984 image-20221210201256846

通过上面两个例子的验证:

▪ 仅有一个先序序列(或中序序列、后序序列),无法确定这颗二叉树的树形!

▪ 思考:给定先序序列、中序和后序遍历序列中任意两个,是否可以唯一确定这颗二叉树的树形?

二叉树的构造

(1) 同时给定一棵二叉树的先序序列和中序序列,就能唯一确定棵二叉树?

• 是!

​ • 定理1

(2) 同时给定一棵二叉树的中序序列和后序序列,就能唯一确定这棵二叉树?

• 是

​ • 定理2

(3) 同时给定一棵二叉树的先序序列和后序序列,就能唯一确定这棵二叉树吗?

• 否

下面我们给出证明:

定理1

▪ 任何n(n>=0)个不同节点的二叉树,都可由它的中序序列和先序序列唯一地确定。

证明(数学归纳法)

• 基础: 当 n=0 时,二叉树为空,结论正确.

• 假设: 设节点数小于n的任何二叉树,都可以由其先序序列和中序序列唯一地确定

• 归纳: 已知某二叉树具有n(n>0)个不同节点,其先序序列是a0a1 …an-1;中序序列是b0b1…bk-1bk+1…bn-1 .

​ ▪ 先序遍历“根-左-右”,a0 必定是二叉树的根节点

​ ▪ a0 必然在中序序列中出现,设在中序序列中必有某个bk(0<=k<=n-1)就是根节点a0

image-20221210210634563

• 由于bk是根节点,中序遍历“左-根-右”,故中序遍历中

​ ▪ b0b1…bk-1必是根节点bk(a0)左子树的中序序列,即bk的左子树有k个节点

​ ▪ bk+1…bn-1必是根节点bk(a0)右子树的中序序列,即bk的右子树有n-k-1个节点

• 对应先序序列,紧跟在根节点a0之后的k个节点a1…ak是左子树的先序序列,ak+1…an-1,这n-k-1就是右子树的先序序列.

• 根据归纳假设,子先序序列a1…ak和子序序列b0b1…bk-1可以唯一地确定根节点a0的左子树,而先序序列ak+1…an-1和子中序序列bk+1…bn-1可以唯一地确定根节点a0的右子树.

image-20221210212041852

通过上面的证明,我们从先序遍历和中序遍历进行逐层分解,唯一确定了一个二叉树.进而逆向证明了二叉树是可以通过其先序遍历和中序遍历唯一确定.

我们观察下面例子:

image-20221210214837749

①通过先序遍历序列的第一个节点,即可确定二叉树的根。

②我们根据得到的根查找中序遍历序列,就可以找到此二叉树的根。

​ 根据中序遍历的特点就可以得知:根节点的左边就是其左子树的中序遍历序列,其右边就是其右子树的中序遍历序列

③我们通过查找中序序列的根的左边的节点个数,就可以确定二叉树的左子树,根据根右边的节点个数,就可以确定二叉树的右子树。

④ 根据中序序列的第二个节点,就可以确定下一层级的根节点,然后拿这个根节点去查找中序遍历的序列,就可以找到此层级的左子树和右子树,以此类推。

所以我们可以根据上面证明的性质,进行二叉树的构造

算法实现

框架:

BTNode *CreateBT1(先序序列,中序序列,处理的本层级的二叉树节点个数)

{
	如果传入的二叉树节点个数是0,则返回空;

    否则,为新节点申请空间;
    
    在先序序列第一个节点确定二叉树的根;
    
    拿着根节点在中序序列找到根节点位置k;
    
    然后我们拿着这个序列就可以确定本层级的根的左右子树,
    就可以构造下一层级的二叉树了.

	返回构造的二叉树即可;        
}

image-20221211163945664

代码实现:

//传入先序序列,中序序列,本层级处理的二叉树节点个数
BTNode *CreateBT1(char *pre,char *in,int n)
{
    //定义访问二叉树的指针
    BTNode *s;
    //定义寻找二叉树的根的中间变量
    char *p;
    //定义根节点的位置k
    int k;
    //先判断二叉树是否为空
    if(n<=0)
    {
        return NULL;
    }        
    //如果通过上述验证,则不为空,为根节点申请空间
    s = (BTNode *)malloc(sizeof(BTNode));
    //根节点数据区赋值,即为先序序列pre的第一个字符
    s->data = *pre;
    //现在根找到了,就去找二叉树的左右子树
    //这就需要借助中序序列了,中序序列遍历顺序为左->根->右,所以先找到根,就可以找到其左子树
    //在中序中找根节点的位置k
    for(p=in;p<in+n;p++)	//in是传入的in数组开始的位置
    {
         if(*p==*pre)
         {
             break;
         }    
    }
    //找到根节点的位置,我们就找到了此层级的二叉树的根,同时我们也就可以通过中序序列数组                                    
    //确定二叉树左子树的个数和右子树的个数, 为下一层级构造做准备
	k = p-in;	//根开始位置减去数组开始位置,就是左子树个数
    //构造左右子树
    s->lchild = CreateBT1(pre+1,in,k);
    //pre+1:下一层级的左子树根,我们对先序序列指针后移一位
    //in: 中序序列,左子树仍然是从头开始
    //k : 左子树个数就是上面求的
	s->rchild = CreateBT1(pre+k+1,p+1,n-k-1);
    //右子树的根,我们既然已经知道左子树的个数,就知道根在先序序列第几位
    //pre+k+1: 右子树的先序序列是根右边的,我们通过查个数即可知道其开始的位序=开始+左子树+1
    //p+1: 右子树的中序序列是根右边开始的,所以从根的位置p+1即可
    //n-k-1: 右子树的个数是总是减去左子树,再减去根
    //最后返回构造的二叉树即可
    return s;
}

定理2

▪ 任何n (n>0)个不同节点的二叉树,都可由它的中序序列和后序序列唯一地确定.

证明:

如下图:

image-20221211171417540

通过构造二叉树的先序序列和中序序列,后序序列,我们可以发现,每一步都是有条不紊的,每一步都是分层次的,我们通过构造序列的过程,逆向可以构造出二叉树,就间接地证明了,这个定义的合法性.

思维拓展:

为什么中序遍历和先序遍历

中序遍历和后序遍历可以唯一确定一棵二叉树

定时先序遍历和后序遍历就不能呢?

我们可以从同一层级的构造上面进行直观理解:

中序遍历是 : 左-根-右 ---->通过根, 就可以唯一确定本层次的左右子树的节点个数

先序遍历: 根-左-右 ----->根是必然是第一个, 不确定的就是左子树和右子数

后序遍历: 左-右-根 ----->根必然是最后一个节点,不确定的就是左子树和右子树

这样就理解了吧,我们下节ヾ( ̄▽ ̄)Bye>Bye!

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

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

相关文章

C++类和对象--封装

目录 1.封装 1.1封装的意义一--将属性和行为作为一个整体 1.1.1成员属性&#xff0c;成员变量&#xff0c;成员函数&#xff0c;成员方法 1.2封装的意义二--将属性和行为加以控制&#xff0c;公共权限&#xff0c;保护权限&#xff0c;私有权限 1.3struct和class区别 1.4成员…

物联网-异步控制多个设备

物联网-异步控制设备 背景 在这个万物互联的时代&#xff0c;物联网设备起到了关键性的作用&#xff0c;那我们怎么去联动一个个物联网设备。比如一个家庭&#xff0c;里面有很多的设备&#xff0c;比如洗衣机&#xff0c;加湿器、空调、除湿机、灯光等等这些智能设备。假如在…

攻击类型分布

执行摘要 从 1987 年 9 月 14 日&#xff0c;中国向世界发出第一封电子邮件到如今&#xff0c;中国的互联网 发展已过去整整 31 个年头。从消费互联、产业互联到万物互联&#xff0c;互联网正在加速改变我们的交流方式和交易方式&#xff0c;一次次 004.重塑了国家的经济形态和…

【Flutter 组件】001-关于 Widget 的一切

【Flutter 组件】001-关于 Widget 的一切 文章目录【Flutter 组件】001-关于 Widget 的一切一、概述1、Widget 基本概述2、Flutter Framework 里的 Widget架构图说明3、根 Widget二、Widget 类1、Widget 的功能2、Widget 类源码说明Widget 的标识符&#xff1a;KeyFlutter 中如…

【云原生 | Kubernetes 实战】10、K8s 控制器 Deployment 入门到企业实战应用(上)

目录 一、Deployment 控制器&#xff1a;概念、原理解读 1.1 Deployment 概述 1.2 Deployment 工作原理&#xff1a;如何管理 rs 和 Pod&#xff1f; 补充&#xff1a;什么叫做更新节奏和更新逻辑呢&#xff1f; 二、Deployment 资源清单文件编写技巧 三、Deployment 使…

Java线程 (使用Callable实现多线程),看完你发现多线程多么简单!

1.Thread 与 Runnable 的关系 2.Callable实现多线程 3.线程运行状态 1.Thread 与 Runnable 的关系 经过一系列的分析之后可以发现&#xff0c;在多线程的实现过程之中已经有了两种做法&#xff1a;Thread类、Runnable接口&#xff0c;如果从代码结构本身来讲&#xff0c;使…

电子学会2020年9月青少年软件编程(图形化)等级考试试卷(一级)答案解析

青少年软件编程&#xff08;图形化&#xff09;等级考试试卷&#xff08;一级A卷&#xff09; 分数&#xff1a;100.00 题数&#xff1a;37 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 1. 下面哪个积木能够调节左右声道的音…

疯狂加持,腾讯大佬的“百万级”JVM学习笔记,从思维图+核心+架构让你一步到位

前言 毫不夸张地说&#xff0c;JVM是现代软件工程最成功的案例之一。因为它自带GC&#xff0c;又有无数可以微调的参数&#xff0c;且运行极其稳定可靠&#xff0c;所以&#xff0c;许多厂商的核心业务系统&#xff0c;才敢放心地用Java编写&#xff0c;运行在JVM之上。 近几…

中英翻译《Thailand泰国》

Thailand 泰国 一、Pre-reading activity 阅前思考 1.Find Thailand in an atlas. 在地图册上找到泰国。 2.What are the names of the countries next to it? 与它相邻的国家都叫什么名字&#xff1f; 3.Is your country near Thailand? 你的国家靠近泰国吗&#xff1f; …

Java基于JSP的小区物业管理系统

经济的飞速发展,促使着城市化进程的加快,随之而来的则是人们生活水平日益提高,并促进住宅小区建设的飞速发展。大量住宅小区投入使用后,加大了管理者的工作难度,小区物业除了要对房屋本身进行修缮外,还需对场地、住户信息、附属设备、环卫绿化、收费情况、治安等方面进行专业化…

全国高校计算机能力挑战赛初赛试题全记录

今天搞了mini版蓝桥杯比赛&#xff0c;有时间的话&#xff0c;我们每天都会补充15道主观题。废话不多说&#xff0c;开整&#xff01;&#xff01;&#xff01; 2022.10.11 抽象&#xff1a;在C中&#xff0c;如果一个类并没有什么实际信息&#xff0c;那么就是一个抽象类 多态…

基于java+springboot+mybatis+vue+mysql的招生管理系统

项目介绍 招生管理系统采用java技术&#xff0c;基于springboot框架&#xff0c;vue技术&#xff0c;mysql数据库进行开发。本系统主要包括管理员和学生两个角色组成&#xff0c;主要包括以下功能&#xff1a; &#xff08;1&#xff09;前台&#xff1a;首页、专业信息、招生…

Online DDL和Cardinality

Online DDL和Cardinality前言Fast Index CreationOnline Schema ChangeOnline DDLCardinality什么是CardinalityCardinality是如何进行统计的前言 本文来聊聊关于Mysql索引管理方面的一些内容&#xff0c;首先我们先准备一张表: CREATE DATABASE IF NOT EXISTS test;USE test…

JVM,你是不是过分了?

以我的经验加上和同行们的交流&#xff0c;我认为学 JVM 最好的方法是&#xff1a; 在程序员不同的水平段&#xff0c;做精准的学习。 所谓的精准学习&#xff0c;就是学习对自己工作有巨大帮助的知识点。以工作内容带动学习&#xff0c;等到积累多了&#xff0c;再一举攻克所…

D-027 SerDes详解

SerDes详解1 SerDes简介1.1 并行总线接口1.2 SerDes接口1.3 SerDes的特点2 发送均衡技术1 SerDes简介 1.1 并行总线接口 在SerDes流行之前&#xff0c;芯片之间的互联时通过系统同步或者源同步的并行接口进行接口传输数据。 并行接口定义图片系统同步发送端和接收端都是由系…

影驰H610MK主板在MBR硬盘上安装系统(可用于安装WIN7)

记录一次MBR格式的机械硬盘安装WIN10系统。 一、进入BIOS界面 二、设置BIOS界面 1、设置系统模式&#xff1a;高级->系统模式选择&#xff0c;选择Legacy and UEFI &#xff08;默认模式为UEFI&#xff09; 2、设置CSM配置 1&#xff09;、进入CMS配置界面&#xff1a;高级…

Js实现简单的文件类型、文件大小、图片像素校验

文章目录1、简单的小Demo2、更多说明2.1 利用循环判断DOM是否渲染完成2.2 利用MutationObserver监听DOM树变化2.3 关于节点的宽高属性2.4 关于页面的宽高属性2.5 关于FileReader提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 1、简单的小Demo <!DO…

“互联网+”时代保险公司经营管理模式研究

目 录 摘 要 3 引言 4 一、公司经营管理模式的理论概述 5 &#xff08;一&#xff09;“互联网”的概念 5 &#xff08;二&#xff09;企业经营管理的主要模式 5 二、众安保险公司的基本情况 6 三、众安公司经营管理模式面临的困难 8 &#xff08;一&#xff09;经营管理方式滞…

关于SpringBoot集成ES Scroll API(滚动查询)的实践

待到秋来九月八&#xff0c;我花开后百花杀背景&#xff1a;大胆尝试实践&#xff1a;学习踩坑最终解决背景&#xff1a; 那是年初在某个交付项目&#xff0c;从用户侧获知了一个elastic search作为分布式数据库的一个瓶颈&#xff0c;那就是单次查询量超过了ES的默认单次查询…

DirectX12 - Pipeline(管线)之IA

这里是SunshineBooming&#xff0c;GPU公司一枚小小的Driver工程师&#xff0c;主要工作是写DirectX12 Driver&#xff0c;我会持续更新这个DX12 Spec系列&#xff0c;可能比较冷门&#xff0c;但是都是干货和工作中的心得体会&#xff0c;有任何GPU相关的问题都可以在评论区互…