内容预览

  • 零、读前说明
  • 一、树转换为二叉树
  • 二、二叉树转换为树
  • 三、二叉树转换为森林
  • 四、森林转换为二叉树
  • 五、树与森林的遍历
    • 5.1、树的遍历
    • 5.2、森林的遍历

零、读前说明

  • 本文中所有设计的代码均通过测试,并且在功能性方面均实现应有的功能。
  • 设计的代码并非全部公开,部分无关紧要代码并没有贴出来。
  • 如果你也对此感兴趣、也想测试源码的话,可以私聊我,非常欢迎一起探讨学习。
  • 由于时间、水平、精力有限,文中难免会出现不准确、甚至错误的地方,也很欢迎大佬看见的话批评指正。
  • 嘻嘻。。。。 。。。。。。。。收!

摘要   

  在满足树的条件下,树可以是任意形状,一个节点可以有任意多个孩子。在前面的存储结构中,提到了树的孩子兄弟方法可以将一个树用二叉链表进行存储,所以借助二叉链表,树和二叉树可以进行相互转换,从物理结构来看,他们的二叉链表是相同的。因此,只要我们设定一定的规则,用二叉树来表示树甚至森林是可以,森林与二叉树也可以相互转换。(摘自《大话数据结构》 P196 )

  关于树、森林、二叉树等基础知识等,可以查看博文:数据结构(十) – C语言版 – 树 - 基础知识。

一、树转换为二叉树

  在前面的博文 数据结构(十) – C语言版 – 树 - 基础知识 里面已经说过了树的 左孩子-右兄弟表示法,他就可以将一个转化为一个类二叉树(没有区分左右孩子节点)。具体转换的方法可以总结为:

  1、加入连接线 :在树中所有的兄弟节点(同一双亲下的同一层的节点(孩子之间互称兄弟))之间加入一条连接线
  2、删除连接线 :对树中每一个节点,只保留他与最左边第一个孩子节点的连接点,删掉他与其他孩子节点的连接线
  3、调整层次顺序:以树的根节点为根节点,依次按照连接线的形式将节点调整到层次分明,左右清楚

  注意 :第一个孩子节点是二叉树根节点的左孩子,兄弟节点转换过来的孩子节点是右孩子

  举个栗子:用下图中表示的树进行举例说明,其中因为是一个简单的树的结构,在一个节点下面可能会有任意多个节点,所以也就是没有左右节点的说法了, 这里我们使用左右的顺序关系,从左依次到右来表示。
  

图1.1 树的简单表示形式

  
  从上面的图片在中,我们可以看到,节点 B、C、D 为一组兄弟节点,节点 E、F 为一组兄弟节点、节点 H、I、J 为一组兄弟节点,那么首先将各个兄弟节点连接起来,下图左侧表示( 红色 线条)。

  然后将除了长子(最左边节点)节点之间的连接线删除(下图中右侧用 灰色虚线 表示)。

图1.2 兄弟加线、删线的图例

  
  然后进行节点层次的调整,图中节点 B 为节点 A 的长子,节点 E 为节点 B 的长子,节点 H 为节点 D 的长子,那么在调整时,将长子调整为节点的左孩子,然后将兄弟节点调整为其右孩子。所以,节点 B、E、H 分别为其双亲节点的左孩子其他兄弟节点为右孩子。并且节点 H、I、J 为兄弟节点,在调整过程中,将节点 I 调整为节点 H 的右孩子,节点 G 为 I 的右孩子,调整效果如下图所示。
  

图1.3 层次调整示意图

  

二、二叉树转换为树

  这个相对比较简单了,其实就是上面的一个逆过程,但是实际的操作过程还是先加线、再删线、后调整次序的过程,只是操作的对象略有不同。那么其转换的过程可以描述为:

  1、连接节点:如果节点存在左孩子,那么将这个左孩子的右孩子节点、右孩子的右孩子节点,右孩子的右孩子的右孩子节点…都和此节点连接起来
  2、删除连接:删除原本二叉树中的所有节点与其右孩子节点的连接线
  3、调整层次:依次按照连接线的形式将节点调整到层次分明,左右清楚

  过程可以用下面的图片来一次表示。

  首先如下图左边的二叉树为例,我们分别将右孩子、右孩子的右孩子…都与爷爷节点连接起来(下图中右边图例中 红色 线条表示)。

图2.1 节点连接示意图

  然后将二叉树中所有节点和其右孩子的连接线删除,如下图所示(灰色虚线表示)。

图2.2 删除节点连接示意图

  
  最后调整完层次后,可以得到和上图1.1中一模一样的树。详情 点我可以查看图1.1。

  但是有一个问题:上面的二叉树的根节点是没有右孩子的,所有可以将二叉树转换成树。那么如果根节点存在右孩子,那么应该怎么转换呢?看看下面。

三、二叉树转换为森林

  首先来看看什么是森林?

  森林:指的是多个不相交的树的集合

  根据前面的标识。可以将一个二叉树转换为树,那么应该怎么转换为森林呢?

  判断一个二叉树能够转换成树还是森林,需要判断根节点是否存在右孩子,存在右孩子就是森林,不存在右孩子就是树。

  所以,将一个二叉树转换为森林就可以总结为:

  1、从根节点开始,如果存在右孩子,则将其与右孩子的连接线删除,然后在判断分离后的二叉树,如果存在右孩子则删除连接线…直到所有的与右孩子的连接线删除为止。

  2、将每一个分离出来的二叉树转换为树即可。具体可以 点我可以查看详细步骤。

  过程可以用下面的图片来一次表示。

  首先将右孩子的连接线断开(下图中虚线表示)。

图3.1 断开右孩子连线

  
  然后将二叉树转换为树即可,如下图表示。
  

图3.1 断开右孩子连线

  

四、森林转换为二叉树

  在森林中,有若干个独立的树组成,下图所示。
  

图4.1 层次调整示意图

  
  那么将一个森林转换成一个二叉树,那么可以现需要将每个独立的树先转换成二叉树,然后将多个二叉树在组合成二叉树接口。所以,具体的方法可以描述为:

  1、将树中每一个树转换成二叉树,转换方式与前面的一致。
  2、第一个二叉树不动,从第二个二叉树开始,依次把后面的一个二叉树的根节点作为前一个二叉树的根节点的右孩子链接起来(也就是将各个树的根节点依次从左到右链接)。直到所有二叉树链接完成。

  所以,具体的步骤可以用下面来表示。

  首先将每一个树转换成二叉树,还是使用左孩子有兄弟的方式来转换,转换完成如下图所示。

图4.2 每个树转换为二叉树

  然后依次拼接二叉树,作为根节点的右孩子,其实也就是将各个树的根节点从左到右依次链接起来,然后稍微调整层次即可完成,所以如下图所示。

图4.3 依次链接各个树

  

五、树与森林的遍历

  树和森林的遍历是比较复杂和困难的,所以前面才大量的说明二叉树的相关的操作。

5.1、树的遍历

  树的遍历分为两种方式:

    一种是先根遍历:先访问树的根节点,然后依次在先根遍历每一个子树,同样也是一个递归的定义
    一种是后根遍历:先依次遍历每一个子树,然后依在遍历根节点,同样也是递归的定义。

  先根遍历的顺序如下图所示。

图5.1 先根遍历示意图

  
  按照图中 p1、p2、p3、p4、p5、… 依次进行遍历,其中节点 B 为节点 A 的孩子节点,但同时也是节点E 和节点F 的双亲结点。所以可以得到其遍历结果为:

A->B->E->F->C->G->D->H->I->J

  
  后根遍历的顺序和先跟正好相反,如下图所示。

图5.2 后根遍历示意图

  
  按照图中 p1、p2、p3、p4、p5、… 依次进行遍历,所以可以得到其遍历结果为:

E->F->B->G->C->H->I->J->D->A

5.2、森林的遍历

  森林的遍历也是有两种遍历顺序,分别为:前序遍历、后序遍历。

  1、先将森林中的每一个树都按照先根遍历、后根遍历的顺序遍历
  2、然后依次从左到右将每一个树的遍历结果合并到一起即为森林的遍历。
  3、树的先根遍历对应于森林的先序遍历,树的后根遍历对应森林的后序遍历

  总结:

    森林,树的前序(根)遍历和二叉树的前序遍历的结果相同
    森林、树的后根(序)遍历和二叉树的中序遍历的结果相同

  所以,当以二叉链表作为树的存储结构时,树的先根遍历和后根遍历完全可以借用二叉树的先序遍历和中序遍历的算法来实现,这其实也证实,我们找到了对树和森林这种复杂问题的简单解决办法。(摘自《大话数据结构》P200)

  
  好啦,废话不多说,总结写作不易,如果你喜欢这篇文章或者对你有用,请动动你发财的小手手帮忙点个赞,当然关注一波那就更好了,好啦,就到这儿了,么么哒(*  ̄3)(ε ̄ *)。

上一篇:数据结构(十八) – C语言版 – 树 - 二叉树的线索化及遍历 – 线索化后的直接前驱、后继获取
下一篇:数据结构(二十) – C语言版 – 树 - 霍夫曼树(哈夫曼树、赫夫曼树、最优二叉树)、霍夫曼编码

数据结构(十九) -- C语言版 -- 树 - 树、森林、二叉树的江湖爱恨情仇、相互转换相关推荐

  1. 数据结构c语言版题库编程,数据结构习题库(c语言版)

    <数据结构习题库(c语言版)>由会员分享,可在线阅读,更多相关<数据结构习题库(c语言版)(104页珍藏版)>请在人人文库网上搜索. 1.wages in arrears. 2 ...

  2. 构建线性表的c语言代码,数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码...

    1.运行环境 这里说明一下这里所有的C语言代码都是基于code::blocks 20.03编译运行的.当然一些其他集成开发环境应该也是可以的,个人不太喜欢功能太过强大的IDE,因为那同样意味着相关设置 ...

  3. 数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码

    数据结构严蔚敏C语言版-线性表顺序存储结构(顺序表)C语言实现相关代码 1.运行环境 2.准备工作 1)项目构建 1>新建一个SeqList项目 2>新建两个文件Sources和Heade ...

  4. 《数据结构与算法 C语言版》—— 3.8习题

    本节书摘来自华章出版社<数据结构与算法 C语言版>一 书中的第3章,第3.8节,作者:徐凤生,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 3.8习题 1名 ...

  5. 《数据结构与算法 C语言版》—— 2.5上机实验

    本节书摘来自华章出版社<数据结构与算法 C语言版>一 书中的第2章,第2.5节,作者:徐凤生,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2.5上机实验 实 ...

  6. 《数据结构与算法 C语言版》—— 2.7习题

    本节书摘来自华章出版社<数据结构与算法 C语言版>一 书中的第2章,第2.7节,作者:徐凤生,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2.7习题 1描 ...

  7. c语言数据结构算法设计题,数据结构题集(C语言版)算法设计题答案[].doc

    数据结构题集(C语言版)算法设计题答案[].doc 第一章 绪论 1.16 void print_descending(int x,int y,int z)// 按从大到小顺序输出三个数 { scan ...

  8. 大白话5分钟带你走进人工智能-第二十九节集成学习之随机森林随机方式 ,out of bag data及代码(2)

              大白话5分钟带你走进人工智能-第二十九节集成学习之随机森林随机方式 ,out  of  bag  data及代码(2) 上一节中我们讲解了随机森林的基本概念,本节的话我们讲解随机森 ...

  9. 初学者对C语言中指针的爱恨情仇

    C语言中指针和数组的爱恨情仇 文章目录 C语言中指针和数组的爱恨情仇 一.前言 二.为什么学指针 三.说明 四.跟我一起学 (一)C语言中的*和& 1.C语言中为什么存在&和* 2.& ...

最新文章

  1. LIVE 预告 | CMU研究者:解放审稿人,AI可以帮我们实现自动审稿吗?
  2. go语言的iota是什么意思_关于Golang中的iota
  3. 一些很特别的J2ME开源项目
  4. Chillingo分享三款游戏图标的设计经验
  5. time模块及datetime模块常用方法讲解
  6. 如何在JSP里使用Java bean
  7. 新手必学的java报表开发工具FineReport实用技巧
  8. 今天终于可以正常下班了
  9. 44rwx权限45权限说明案例46修改权限
  10. qt socket 传递结构体 结构体中有list_GO语言入门-14、结构体
  11. HTML学习总结(4)——表格/块/内联元素/iframe/颜色/脚本/实体
  12. python中fac函数_python系列-基础
  13. ug安装计算机用户名不能是汉字,win7系统下安装UG软件后打开提示计算机名不对怎么办...
  14. 直播丨易鲸捷SQL编译器、达梦DM8数据库体系结构
  15. Java学习笔记 | Java异常处理
  16. 秦九韶算法的思想与解多项式算法时间比较附代码
  17. 微信公众号文章采集思路
  18. FreeTextBox编辑框遇到的问题
  19. android 9.0 SystemUI状态栏下拉快捷添加截图快捷开关
  20. 强改微信内置浏览器——让x5内核滚粗

热门文章

  1. Oracle连接本地超时提示【ORA-12170 TNS 】之解决办法
  2. 安全联网设备客户端登录
  3. Ryan二号的控制界面
  4. C语言进阶之自定义类型:结构体,枚举,联合
  5. 从“熵理论到熵减”的过程
  6. Python读写EXCEL文件常用方法大全
  7. 如何下载天桥街道卫星地图高清版大图
  8. Surface Go为教育而生,微软将如何改变中国课堂?
  9. mixer_path.xml 研究
  10. python模拟自动填充(一)