树的应用 —— 二叉树的遍历【层次遍历、遍历序列还原树】

article/2025/9/18 21:31:00

树的应用 —— 二叉树的遍历【层次遍历、遍历序列还原树】

【层次遍历】

二叉树的遍历一般有先序遍历、中序遍历和后序遍历,除了这三种遍历,还有另一种遍历方式——层次遍历,即按照层次的顺序从左向右进行遍历。

一棵树如下图所示。

层次遍历的流程:首先遍历第1层A,然后遍历第2层,从左向右B、C,再遍历第3层,从左向右D、E、F,再遍历第4层G。

在这里插入图片描述

[层次遍历的秘籍]

首先遍历第1层,然后第2层……同一层按照从左向右的顺序访问,直到最后一层。

[程序如何实现层次遍历?]

通过观察可以发现,先被访问的节点,其孩子也先被访问,先来先服务,因此可以用队列实现。

[完美图解]

在这里插入图片描述
以上图的二叉树为例,展示层次遍历的过程。

① 首先创建一个队列Q ,令树根入队,如下图所示(注意: 实际上是指向树根A的指针入队,为了图解方便,将数据入队)。

在这里插入图片描述

② 队头元素出队,输出A,同时令A的孩子B、C入队(按从左向右的顺序进行,如果是普通树,则包含所有孩子)。二叉树和队列的状态如下图所示。

在这里插入图片描述

③ 队头元素出队,输出B,同时令B的孩子D、E入队,如下图所示。

在这里插入图片描述

④ 队头元素出队,输出C,同时令C的孩子F入队。二叉树和队列的状态如下图所示。

在这里插入图片描述

⑤ 队头元素出队,输出D,同时令D的孩子入队,D没有孩子,什么也不做。

在这里插入图片描述

⑥ 队头元素出队,输出E,同时令E的孩子入队,E没有孩子,什么也不做。

在这里插入图片描述

⑦ 队头元素出队,输出F,同时令F的孩子G入队。二叉树和队列的状态如下图所示。

在这里插入图片描述

⑧ 队头元素出队,输出G,同时令G的孩子入队,G没有孩子,什么也不做。

在这里插入图片描述

⑨ 队列为空,算法结束。

[算法代码]

void Leveltraverse(Btree T){Btree p;if(!T){return false;}queue<Btree>Q;  //创建一个普通队列【先进先出】,里面存放指针类型Q.push(T); //根指针入队while(!Q.empty){ //如果队列不空p = Q.front(); //取出队头元素作为当前节点Q.pop(); //队头元素出队cout << p->data << " ";if(p->lchild){Q.push(p->lchild); //左孩子指针入队}if(p->rchild){Q.push(p->rchild); //右孩子指针入队}}return true;
}

【遍历序列还原树】

根据遍历序列可以还原这棵树,包括二叉树还原、树还原和森林还原三种还原方式。

一 [二叉树还原]

由二叉树的先序和中序序列,或者中序和后序序列,可以唯一地还原一棵二叉树。

注意:【由二叉树的先序和后序序列不能唯一地还原一棵二叉树。】

[算法步骤]

① 先序序列的第1个字符为根

② 在中序序列中,以根为中心划分左、右子树;

③ 还原左、右子树。

[完美图解]

已知一棵二叉树的先序序列ABDECFG和中序序列DBEAFGC,还原这棵二叉树。

① 先序序列的第1个字符A为根,在中序序列中以A为中心划分左、右子树,左子树包含D、B、E三个节点,右子树包含F、G、C三个节点。

在这里插入图片描述

② 左子树DBE,在先序序列中的顺序为BDE,第1个字符B为根,在中序序列中以B为中心划分左、右子树,左、右子树各只有一个节点,直接作为B的左、右孩子。

在这里插入图片描述

③ 右子树FGC,在先序序列中的顺序为CFG,第1个字符C为根,在中序序列中以C为中心划分左、右子树,左子树包含F、G节点,右子树为空。

在这里插入图片描述

④ 左子树FG,在先序序列中的顺序为FG,第1个字符F为根,在中序序列中以F为中心划分左、右子树,左为空,右子树只有一个节点G,作为F的右孩子即可。

在这里插入图片描述

[算法代码]

BiTree pre_mid_createBiTree(char *pre , char *mid, int len){ //由先序、中序还原建立二叉树if(len == 0){return NULL;}char ch = pre[0]; //先序序列中的第1个节点,作为根int index = 0; //在中序序列中查找根节点,并用index 记录查找长度while(mid[index] != ch){ //在中序序列中查找根节点,左边为该节点的左子树,右边为右子树index ++;}BiTree T = new BiTNode; //创建根节点T->data = ch;T->lchild = pre_mid_createBiTree(pre + 1, mid, index);  //创建左子树T->rchild = pre_mid_createBiTree(pre + index + 1,mid + index + 1, len - index - 1); //创建右子树return T;
}

[代码解释]

pre_mid_createBiTree(char *pre, char *mid , int len); //由先序、中序还原建立二叉树

函数有三个参数:pre、mid为指针类型,分别指向先序、中序序列的首地址;len为序列的长度。先序和中序的序列长度一定是相同的。

首先,先序序列的第1个字符pre[0]为根;然后,在中序序列中查找根所在的位置,用index记录查找长度,找到后以根为中心,划分为左、右子树。

  • 左子树:先序序列的首地址为pre+1,中序序列的首地址为mid,长度为index。
  • 右子树:先序序列的首地址为pre+index+1,中序序列的首地址为mid+index+1,长度为len-index-1;右子树的长度为总长度减去左子树的长度,再减去根。

确定参数后,再递归求解左、右子树即可。

第1次的树根及左、右子树划分如下图所示。

在这里插入图片描述

由二叉树的后序序列和中序序列也可以唯一确定一棵二叉树,方法和上面一样,只不过后序序列的最后一个字符为根,然后在中序序列中以根为中心划分左、右子树。

[练习]

已知一棵二叉树的后序序列DEBGFCA和中序序列DBEAFGC,还原二叉树。

[算法代码]

BiTree pro_mid_createBiTree(char *last,char *mid , int len){ //由后序、中序还原建立二叉树if(len == 0){return NULL;}char ch = last[len - 1]; //找到后序序列中的最后一个节点,作为根int index = 0;  //在中序序列中查找根节点,并用index 记录查找长度while(mid[index] != ch){ //在中序序列中找根节点,左边为该节点的左子树,右边为右子树index ++;}BiTree T = new BiTNode;  //创建根节点T->data = ch; T->lchild = pro_mid_createBiTree(last , mid , index); //创建左子树T->rchild = pro_mid_createBiTree(last + index, mid + index + 1,len - index - 1); //创建右子树return T;
}

先序遍历、中序遍历还原二叉树的秘籍:先序找根,中序分左右。
后序遍历、中序遍历还原二叉树的秘籍:后序找根,中序分左右。

二 [树还原]

由于树的先根遍历、后根遍历与其对应二叉树的先序遍历、中序遍历相同,因此可以根据该对应关系,先还原为二叉树,然后把二叉树转换为树。

算法步骤:

  1. 树的先根遍历、后根遍历与其对应的二叉树的先序遍历、中序遍历相同,因此根据这两个序列,按照先序遍历、中序遍历还原二叉树的方法,还原为二叉树。
  2. 将该二叉树转换为树

举个栗子:已知一棵树的先根遍历序列ABEFCDGIH和后根遍历序列EFBCIGHDA,还原这棵树。

完美图解:

  1. 树的先根遍历、后根遍历与其对应的二叉树的先序遍历、中序遍历相同,因此其对应二叉树的先序序列ABEFCDGIH和中序遍历序列EFBCIGHDA,按照先序遍历、中序遍历还原二叉树的方法,还原为二叉树,如下图所示。
    在这里插入图片描述

  2. 按二叉树转换树的规则,将该二叉树转换为树,如下图所示
    在这里插入图片描述

三 [森林还原]

由于森林的先序遍历、中序遍历与其对应二叉树的先序遍历、中序遍历相同,因此可以根据该对应关系,先将其还原为二叉树,然后将二叉树转换为森林。

已知森林的先序遍历序列ABCDEFGHJI和中序遍历序列BCDAFEJHIG,还原森林。

森林的先序和中序对应二叉树的先序和中序,根据该先序和中序序列先将其还原为二叉树,然后将二叉树转换为森林,如下图所示。

在这里插入图片描述


http://chatgpt.dhexx.cn/article/5qgVR2FE.shtml

相关文章

二叉树:层次遍历算法(自上而下,从左到右)

层次遍历&#xff08;LevelOrder&#xff09;就是默认为自上而下&#xff0c;从左到右&#xff0c;一层一层进行遍历&#xff0c; 层次遍历需要借助队列来完成&#xff0c; 队列&#xff1a;先进先出&#xff08;FIFO&#xff09;。 分析&#xff1a;如图有一棵二叉树&#xff…

MATLAB符号运算——微分

微分 微分在数学中的定义&#xff1a;由函数Bf(A)&#xff0c;得到A、B两个数集&#xff0c;在A中当dx靠近自己时&#xff0c;函数在dx处的极限叫作函数在dx处的微分&#xff0c;微分的中心思想是无穷分割。 在MATLAB中计算微分 函数&#xff1a;diff 调用格式&#xff1a; …

matlab中常用符号

在使用MATLAB的过程中&#xff0c;经常需要对输出图形中的变量进行标注&#xff0c;其中经常遇到的难题就是如何标注各种上标、下标、斜体、黑体、箭头、上圆圈、正负号等特殊符号&#xff0c;以及如何标注特殊的数学符号。这里第一机电网给大家总结一下&#xff0c;希望对大家…

MATLAB符号运算(七)

目录 1、实验目的&#xff1a; 2、实验内容&#xff1a; 1、实验目的&#xff1a; 1&#xff09;掌握定义符号对象和创建符号表达式的方法&#xff1b; 2&#xff09;掌握符号运算基本命令和规则&#xff1b; 3&#xff09;掌握符号表达式的运算法则以及符号矩阵运算&#xf…

MATLAB符号运算小技巧

1. 引言 MATLAB具备强大的符号运算功能。符号运算就是所谓的计算机代数&#xff0c;通俗的说就是利用计算机进行数学公式的推导。这篇文章主要总结几个MATLAB进行符号运算时的小技巧&#xff0c;这也是作者在进行技术研究过程中实际碰到的一些难题&#xff0c;希望后来者能少走…

Matlab-运算符

运算符是一个符号&#xff0c;它告诉编译器执行特定的数学或逻辑操作。MATLAB主要用于整个矩阵和阵列的操作。因此&#xff0c;MATLAB中的运算符既可用于标量数据也可用于非标量数据。MATLAB允许以下类型的基本操作 算术运算符 关系运算符 逻辑运算符 按位运算符 集合运算符…

matlab常见符号运算(计算导数,积分、符号求和等))

符号运算的建立 sym 函数用来建立单个符号量&#xff0c;一般调用格式为&#xff1a; 符号变量 sym(A) 参数 A 可以是一个数或数值矩阵&#xff0c;也可以是字符串 syms 命令用来建立多个符号量&#xff0c;一般调用格式为&#xff1a; syms 符号变量1 符号变量2 … 符号变量…

MATLAB符号变量的创建和简单运算

声明&#xff1a;本文章中数据来自清风老师数学建模课程 文章目录 MATLAB符号变量的创建和简单运算1、符号变量1. 1 符号变量的创建1.2 符号方程的创建3 符号矩阵的创建 2、符号运算2.1 简单运算2.2 表达式的整理2.3 因式分解2.4 多项式展开2.5 合并2.6 计算分子与分母2.7 让结…

第十一章:MATLAB:符号运算(符号与数值,符号矩阵)

第十一章&#xff1a;MATLAB符号运算 11.1. 符号与数值11.1.1. 符号与数值间的转换实例-数值与符号转换 11.1.2. 符号表达式与数值表达式的精度设置实例-魔方矩阵的数值解实例-稀疏矩阵的数值解实例-伴随矩阵的数值解实例-托普利兹矩阵的数值解 11.2. 符号矩阵11.2.1. 符号矩阵…

MATLAB的符号运算基础

在数学运算中&#xff0c;运算的结果如果是一个数值&#xff0c;可以称这类运算为数值运算&#xff1b;如果运算结果为表达式&#xff0c;在MATLAB中称为符号运算&#xff0c;符号计算是对未赋值的符号对象(可以是常数、变量、表达式)进行运算和处理。MATLAB具有符号数学工具箱…

MATLAB符号运算——积分

积分 积分是微积分学与数学分析里的一个核心概念。通常分为定积分和不定积分两种。直观地说&#xff0c;对于一个给定的正实值函数&#xff0c;在一个实数区间上的定积分可以理解为在坐标平面上&#xff0c;由曲线、直线以及轴围成的曲边梯形的面积值&#xff08;一种确定的实…

MATLAB的符号计算

MATLAB的符号计算 matlab的符号计算是通过sym、syms 函数去创建符号对象或者符号表达式。例如一元二次函数我们便可以通过syms 函数创建。 syms a b c x y z f1 a * x^2 b * x c; f2 sin(x) * cos(y); f3 (x y)/z; 符号表达式常用运算函数 函数名说明函数名说明facto…

matlab中的符号对象与符号运算

符号对象(Symbolic Objects 不同于普通的数值计算)是Matlab中的一种特殊数据类型&#xff0c;它可以用来表示符号变量、表达式以及矩阵&#xff0c;利用符号对象能够在不考虑符号所对应的具体数值的情况下能够进行代数分析和符号计算(symbolic math operations)&#xff0c;例如…

Matlab系列之符号运算(上)

Matlab系列之符号运算 前言创建符号对象基本操作符号变量的基本操作符号表达式的基本操作四则运算多项式的操作符号表达式化简符号表达式的替换反函数求解复合函数 更多精彩等你发现~ 前言 看到文章的名字&#xff0c;可能很多人都没懂意思&#xff0c;如果叫它的另一个名字&a…

MATLAB学习之符号运算

创建符号变量数值与符号的转换数值矩阵转换为符号矩阵符号替换 本文介绍MATLAB中的符号运算&#xff1b; 1. 创建符号变量 符号常量是不含变量的符号表达式&#xff0c;用 sym 命令来创建符号常量。 sym(‘常量’)&#xff1a;创建符号常量。 asym(sin(2)) sym 命令也可以把…

MATLAB08:符号运算

pdf版本笔记的下载地址: MATLAB08_符号运算&#xff08;访问密码&#xff1a;3834&#xff09; MATLAB08:符号运算 创建符号变量创建符号数字创建符号变量 符号运算符号表达式的化简与代入符号表达式的化简符号表达式的代入 求方程的解析解解单变量方程解多变量方程解方程组 符…

MATLAB基础(三)符号运算

符号对象的建立 符号对象的建立&#xff1a;sym 和 syms sym 函数用来建立单个符号变量&#xff0c;一般调用格式为&#xff1a;符号变量 sym(A) 参数 A 可以是一个数或数值矩阵&#xff0c;也可以是字符串 例如&#xff1a;asym(a) a 是符号变量 bsym(1/3&#xff09; …

MATLAB符号运算部分知识总结

1. 符号表达式的定义 1.1符号变量的定义 符号变量通过命令syms和sym定义&#xff0c;syms命令一次定义一个或多个符号变量&#xff0c;sym命令一次只能定义一个符号变量。定义好的符号函数可以通过命令symvar检查其自变量。 MATLAB系统有默认的符号自变量&#xff0c;主要为&am…

[MATLAB]符号计算

符号计算 一、数值微积分1.1 数值计算与符号计算的区别1.2 符号对象1.3 符号常量1.4 符号变量1.4.1 符号变量的创建1.4.2 创建符号矩阵1.4.3 自由符号变量 1.5 符号表达式1.6 符号计算的运算符1.7 符号运算中的函数运算1.8 符号计算与数值计算的区别 二、符号数字及表达式2.1 数…

MATLAB符号运算

在数学、物理学及力学等各种学科和工程应用中&#xff0c;经常还会遇到符号运算的问题。在MATLAB中&#xff0c;符号运算是为了得到更高精度的数值解&#xff0c;但数值的运算更容易让读者理解&#xff0c;因此在特定的情况下&#xff0c;分别使用符号或数值表达式进行不同的运…