# 森林/树/二叉树相关问题(v1)

森林/树/二叉树相关问题(v1)

树转化二叉树

  • 记:将一般树或者m叉树转化为二叉树的函数为T2BT(T)(参数T是一般树)
    • 注意一般树和m叉树不见得是一回事,关键类比二叉树中,孩子的有序性和相对有序性(特别是独生子树的顺序)
  • 按照层次遍历法一次处理树的每一个结点
  • 在处理任意一个结点的时候,只关心两个方面的东西
    • 是否有孩子(如果有则只关心第一个孩子)
      • 没有的话则该结点的左子树缺失
    • 是否有右兄弟(如果有,则该结点有右孩子)
      • 没有的话,该结点右孩子缺失
      • 一定小心不要把第一个孩子之外的其他孩子作为右孩子!!!
    • 绘图美化
      • 如果是手画,那么将原先是右兄弟的结点绕着其左兄弟顺时针旋转45度左右
  • 应该注意到一个很特别的性质:转换后的二叉树是没有右子树的(对于根结点T)而言!

森林转化为二叉树

  • 将森林转化为二叉树即相当于用孩子兄弟表示法表示森林。

  • 在变化过程中,原森林某结点的第一个孩子结点作为它的左子树,它的兄弟作为它的右子树。

  • 森林 F k F_k Fk是有若干棵树构成的(比如有k棵树, 分别记为 T 1 , T 2 , . . . T k 分别记为T_1,T_2,...T_k 分别记为T1,T2,...Tk)

  • 这些树分别转换为二叉树(执行k次T2BT函数)

    • 得到k棵二叉树,将他们的根结点用兄弟虚线起来,得到 T s T_s Ts
      • 将第一棵树的根也记为 T s T_s Ts,该结点作为转化后的结果二叉树根结点
        • 前面提到,T2BT调用后,得到的树是右子树缺失的,
        • 那么将森林中的右侧的树作为左侧树的右子树就显得很合适
      • 调用T2BT( T s T_s Ts)得到森林转化后的二叉树
    • 或者,干脆就是前一棵树 T i T_i Ti的右孩子结点链接到后一棵 T i + 1 T_{i+1} Ti+1根结点上,就行了

森林/二叉树转化的结点的相关问题

记号说明

  • 记转化前的树为T
    • 转换前的森林为F
  • 树T转化后的二叉树为BT
    • BT=T2BT(T)
  • 森林F转化为二叉树后为FBT
    • FBT=F2BT(F)

左孩子问题(叶子结点问题)

  • 根据树/森林转化为二叉树的算法:

  • 森林中的叶结点由于没有孩子结点,那么转化为二叉树时,该结点就没有左结点,

  • 所以 F 中叶结点的个数就等于T 中左孩子指针为空的结点个数

右孩子问题(分支结点问题)

  • 另外,有一类问题,是关于树转化为二叉树后右孩子缺失问题

  • 通过上面的转化算法可以看到,任意一个结点,

    • 只要它有右兄弟,那么在BT中就不会右孩子缺失

    • 没有右兄弟,那么在BT中一定会缺失右孩子

      • 更一般的,如果接结点x是其双亲结点的最右孩子结点,那么它在BT中也是右孩子缺失的

        • 因此,如果某个结点是其双亲结点的独生子结点,那么它在BT必然是右孩子缺失的
      • 即,每个非终端结点,其所有孩子结点在转换后,最后一个孩子的右指针为空

        • 注意,这仅仅覆盖了全树的n-1个结点(根结点意外的结点有孩子结点的身份)
        • 树T中,只有根结点T不作为任何其他结点的孩子(孩子结点无法覆盖全树)
          • 而根结点转换后,也是右指针为空的
        • 因此转化后的二叉树中,右指针为空的结点数=T的分支结点数+1
      • 但是另一方面,我们的转换算法T2BT告诉我们,根结点也要被当一个左孩子(犹如它之上还有一个虚拟双亲结点S)

        • 这意味着我们可以同一地考察全树的所有结点,它们都有孩子结点的身份
        • 因此转化后的二叉树中,右指针为空的结点数=T的分支结点数+1(包括虚拟的根结点的双亲结点S)
  • 因此,BT中右孩子缺失的结点总数是T中分支结点数+1

思路1(verbose):
  • 没有双亲结点的:(第一层结点)

    • 仅有根结点,我们知道根结点在BT中一定是右孩子缺失的
  • 有双亲结点的:作以下定义(RMC)(对于第2~h层):

    • 结点x有双亲结点,而且是其双亲结点的最后一个孩子(包括唯一孩子的情况),那么这个结点是RMC(RightMostChild)的
    • 另外要考虑根结点,因为我们的转换算法T2BT告诉我们,根结点也要被当一个左孩子(犹如它之上还有一个虚拟结点),因此也特别地把根结点归为RMC类的.
  • 直接统计RMC的含义是明显的,但是并不方便

    • 一个RMC会对应有一个上层分支结点(这个歌RMC结点的双亲结点)
      • 第i层的RMC数量就是第i-1层的分支结点数量
  • 那么BT中的右孩子缺失的结点数就是B中的RMC结点总数+1(根结点)

    • 因为,每个分支结点都会提供一个(且只有一个)RM类的子节点结点
    • T的根结点由于没有双亲结点,因此要单独考虑
或者更直接(concise)
  • 定义WRS(WithoutRightSibling)结点是树T中右兄弟缺失的结点
    • 下面统计各层的WRS数量( L ( i ) 表示第 i 层的 W R S 的数量 L(i)表示第i层的WRS的数量 L(i)表示第i层的WRS的数量)
      • B N ( b r a n c h N o d e ) 分支结点 , B N ( i ) 表示第 i 层的分支结点数量 BN(branchNode)分支结点,BN(i)表示第i层的分支结点数量 BN(branchNode)分支结点,BN(i)表示第i层的分支结点数量
    • L ( 1 ) = 1 L(1)=1 L(1)=1(根结点是WRS)
    • L ( 2 ) = B N ( 1 ) = 1 L(2)=BN(1)=1 L(2)=BN(1)=1(最后一个结点(根结点的最右孩子是WRS))
    • L ( 3 ) = B N ( 2 ) L(3)=BN(2) L(3)=BN(2)
    • ⋮ \vdots
    • L ( h ) = B N ( h − 1 ) L(h)=BN(h-1) L(h)=BN(h1)
  • 又因为所有分支结点(非叶子结点)都分布在** 1 ∼ h − 1 1\sim h-1 1h1**层内, 所以树 T 的所有分支接结点 S u m B r a n c h N o d e s = S B N ( T ) = ∑ i = 1 h − 1 B N ( i ) 所以树T的所有分支接结点SumBranchNodes=SBN(T)=\sum\limits_{i=1}^{h-1}BN(i) 所以树T的所有分支接结点SumBranchNodes=SBN(T)=i=1h1BN(i)
  • 综上,T转化为BT后,所有右孩子缺失的结点数量 W R C ( B T ) = W R S ( T ) = ∑ i = 1 h L ( i ) = 1 + S B N ( T ) WRC(BT)=WRS(T)=\sum\limits_{i=1}^{h}L(i)=1+SBN(T) WRC(BT)=WRS(T)=i=1hL(i)=1+SBN(T)
  • 如果一致一棵树的总结点数N,叶子结点总数SLN,那么可以求得该树的分支结点总数SBN(T)=N(T)-SLN(T)
    • 这样T转化为BT后,具有右孩子缺失的结点总数 W R C ( B T ) = 1 + S B N ( T ) = 1 + N ( T ) − S L N ( T ) WRC(BT)=1+SBN(T)=1+N(T)-SLN(T) WRC(BT)=1+SBN(T)=1+N(T)SLN(T)
对于森林
  • 上述结论基于树T推导,对于森林F,计算公式在形式上是一样的
    • 森林转化为二叉树前也要先将各棵树转换为二叉树,需要注意的仅是各棵二叉树的根结点
    • 后一棵树(根结点)会成为前一棵树的右孩子,这样所有的树的根结点在链接完成后,仅有最后一棵树的根结点还是处于缺失的状态
    • 因此,结论就是,森林F中所有树的分支结点总和+1(由最后一棵树的根结点在FBT中缺失右孩子)
    • WRC(FBT)=1+SBN(F)=1+N(F)-SLN(F)

二叉树转换为森林b2m

二叉树拆分为二叉树森林

  • 由于我们知道由树转化而成的二叉树是没有右子树的
  • 所以,我们可以从大二叉树的右子树入手,将其右子树从大二叉树上断开,记为 T 1 T_1 T1
  • 那么断开的 T 1 T_1 T1的根结点很显然是 T 1 T_1 T1
    • T 1 T_1 T1执行上述操作,知道最后被断开的右子树没有右子树为止

二叉树转为树

  • 根据树转化为二叉树的算法,可以得到二叉树转化为树的算法

  • 可以从根结点开始

    • 按层次遍历的顺序将所有结点划分关系

    • 比如当前处理结点x

      • 如果没有左孩子,说明x本身没有孩子

        • 否则将x的左孩子保留不动
      • 如果有右孩子,那么将右孩子作为x的有兄弟

  • 可以自底向上将二叉树还原为树

    • 最底一层开始,从最右一个结点开始,它作为右子树,那么在原树中作为其双亲结点的最近邻右侧兄弟

树的遍历

  • 这里的树是一般树

  • 树的遍历和二叉树的遍历很相似

  • 树T的先序遍历对应于T2BT(T)的先序遍历的结果序列是一致的

posted @   xuchaoxin1375  阅读(11)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2021-09-27 css_选择器/规则集/属性和值(函数)/计算css选择器的优先级/兼容性规则集/块级元素和行内元素
点击右上角即可分享
微信分享提示