【数据结构】树(三) —— 树、森林与二叉树 的相互转换(C语言版)

一、树转换为二叉树

  1. 加线,所有兄弟结点之间连接一条线;
  2. 去线,对树中的每个结点,只保留它与第一个孩子结点的连线,删除与其他孩子结点之间的连线;
  3. 层次调整,以树的根结点为轴心,将整个树调节一下(第一个孩子是结点的左孩子,兄弟转过来的孩子是结点的右孩子);

在这里插入图片描述
注:树的孩子兄弟表示法 构成转换为 二叉树

结点的左右孩子分别为第一个孩子和此结点的右兄弟。

(1)由于二叉树和树都可以用二叉链表作为存储结构,则以二叉链表作为媒介可导出树与二叉树之间的一个对应关系。

(2)一般树转换成二叉树后,二叉树是没有右子树的(根结点无兄弟)即不是完全二叉树,没有右子树的二叉树也可以转换成森林

(3)一般树转换为二叉树后,结点的左孩子是原来一般树的左孩子,结点的右孩子是原来一般树的兄弟结点。

例题:

二、二叉树转换为树

注: 同样可以用孩子兄弟表示法,逆转化为树

一般树转换为二叉树后,结点的左孩子是原来一般树的左孩子,结点的右孩子是原来一般树的兄弟结点。(任意结点的右孩子为 此结点的右兄弟; 左孩子还是左孩子)

(1)加线。若某结点X的左孩子结点存在,则将这个左孩子的右孩子结点、右孩子的右孩子结点、右孩子的右孩子的右孩子结点…,都作为结点X的孩子。将结点X与这些右孩子结点用线连接起来。(即先将父节点与其所有非第一个孩子结点的结点相连;)

(2)去线。删除原二叉树中所有结点与其右孩子结点的连线。

(3)层次调整。

在这里插入图片描述

在这里插入图片描述

例题:

三、森林转换为二叉树

森林是由若干棵树组成,可以将森林中的每棵树的根结点看作是兄弟,由于每棵树都可以转换为二叉树,所以森林也可以转换为二叉树。

注意:如果一棵树的每个结点最多只有两个子结点,则其可以是树也可以是二叉树。

  1. 把每一棵树转换为二叉树
  2. 第一棵二叉树不动,第二棵树开始,以此把后一棵二叉树的根结点作为前一棵树的根结点的右子树连接起来

在这里插入图片描述
在这里插入图片描述

四、二叉树转换为森林

二叉树转换为森林比较简单,其步骤如下:
(1)先把每个结点与右孩子结点的连线删除,得到分离的二叉树;
(2)把分离后的每棵二叉树转换为树;
(3)整理第(2)步得到的树,使之规范,这样得到森林。

在这里插入图片描述

在这里插入图片描述

总结

判断一棵二叉树 能够转换为 一棵树还是森林, 主要看二叉树的根结点是否有右孩子,有右结点是森林,无右结点是树。(根据孩子兄弟表示法,一棵树的根结点转换为二叉树,其二叉树的根结点无右孩子)

例题:

在这里插入图片描述
解析:

u、v 的四种可能结构:
在这里插入图片描述二叉树的 u结点添加父节点
在这里插入图片描述
二叉树还原为森林:
在这里插入图片描述
在二叉树中添加父节点时,只能在右上方添加,即 U 作为左子树才能表示上方结点为父结点。

答案:B

  • 43
    点赞
  • 215
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
作 者:严蔚敏 李冬梅 吴伟民 出时间:2011-2-1 0:00:00 [1] 字 数:398千字 责任编辑:蒋亮 页 数:236页 开 本:16 ISBN书号:978-7-115-23490-2 所属分类:本科 >> 计算机类 >> 数据结构与算法 所属丛书:21世纪高等学校计算机规划教材——名家系列 定 价:¥28.00元 第1章 绪论 1 1.1 数据结构的研究内容 1 1.2 基本概念和术语 3 1.2.1 数据、数据元素、数据项和数据对象 3 1.2.2 数据结构 4 1.2.3 数据类型和抽象数据类型 6 1.3 抽象数据类型的表示与实现 7 1.4 算法和算法分析 11 1.4.1 算法的定义及特性 11 1.4.2 评价算法优劣的基本标准 11 1.4.3 算法的时间复杂度 12 1.4.4 算法的空间复杂度 14 1.5 小结 15 习题 16 第2章 线性表 18 2.1 线性表的类型定义 18 2.1.1 线性表的定义和特点 18 2.1.2 线性表的抽象数据类型定义 18 2.2 线性表的顺序表示和实现 19 2.2.1 线性表的顺序存储表示 19 2.2.2 顺序表中基本操作的实现 20 2.3 线性表的链式表示和实现 24 2.3.1 单链表的定义和表示 24 2.3.2 单链表基本操作的实现 26 2.3.3 循环链表 31 2.3.4 双向链表 32 2.4 线性表的应用 34 2.4.1 一般线性表的合并 34 2.4.2 有序表的合并 35 2.4.3 一元多项式的表示及相加 37 2.5 小结 40 习题 41 第3章 栈和队列 44 3.1 栈 44 3.1.1 栈的类型定义 44 3.1.2 顺序栈的表示和实现 45 3.1.3 链栈的表示和实现 47 3.2 栈的应用 48 3.2.1 数制转换 49 3.2.2 括号匹配的检验 49 3.2.3 表达式求值 51 3.3 栈与递归 54 3.3.1 采用递归算法解决的问题 54 3.3.2 递归过程与递归工作栈 57 3.3.3 递归算法的效率分析 59 3.3.4 将递归转换为非递归的方法 60 3.4 队列 61 3.4.1 队列的类型定义 61 3.4.2 循环队列——队列的顺序表示和实现 62 3.4.3 链队——队列的链式表示和实现 65 3.5 队列的应用 67 3.6 小结 69 习题 69 第4章 串、数组和广义表 73 4.1 串 73 4.1.1 串的类型定义 73 4.1.2 串的存储结构 75 4.1.3 串的模式匹配算法 76 4.2 数组 83 4.2.1 数组的类型定义 83 4.2.2 数组的顺序存储 84 4.2.3 特殊矩阵的压缩存储 85 4.3 广义表 87 4.3.1 广义表的定义 87 4.3.2 广义表的存储结构 88 4.4 小结 90 习题 91 第5章 二叉树 94 5.1 的定义和基本术语 94 5.1.1 的定义 94 5.1.2 的基本术语 96 5.2 二叉树 97 5.2.1 二叉树的定义 97 5.2.2 二叉树的性质 100 5.2.3 二叉树的存储结构 102 5.3 遍历二叉树和线索二叉树 103 5.3.1 遍历二叉树 103 5.3.2 线索二叉树 109 5.4 森林 114 5.4.1 的存储结构 114 5.4.2 森林二叉树转换 116 5.4.3 森林的遍历 116 5.5 赫夫曼及其应用 117 5.5.1 赫夫曼的基本概念 117 5.5.2 赫夫曼的构造算法 118 5.5.3 赫夫曼编码 121 5.6 小结 123 习题 123 第6章 图 126 6.1 图的定义和基本术语 126 6.1.1 图的定义 126 6.1.2 图的基本术语 128 6.2 图的存储结构 129 6.2.1 邻接矩阵 130 6.2.2 邻接表 132 6.3 图的遍历 135 6.3.1 深度优先搜索 135 6.3.2 广度优先搜索 138 6.4 图的应用 139 6.4.1 最小生成 139 6.4.2 最短路径 144 6.4.3 拓扑排序 150 6.4.4 关键路径 153 6.5 小结 158 习题 160 第7章 查找 164 7.1 查找的基本概念 164 7.2 线性表的查找 165 7.2.1 顺序查找 165 7.2.2 折半查找 166 7.3 表的查找 169 7.3.1 二叉排序 170 7.3.2 平衡二叉树 176 7.3.3 B- 182 7.3.4 B+ 190 7.4 散列表的查找 192 7.4.1 散列表的基本概念 192 7.4.2 散列函数的构造方法 1
5.1 数的逻辑结构 5.1.1 1、的定义 在中常常将数据元素称为结点 (1)有且仅有一个特定的称为根的结点; (2)当n>1时,除根结点之外的其余结点被分成m(m>0)个互不相交的有限集合T1,T2,•••Tm,其中每个集合又是一棵,并称为这个节点的子。 2、的基本术语: 结点的度、的度 叶子节点、分支结点 孩子节点、分支结点、兄弟节点 路径、路径长度 祖先、子孙 结点的层数、的深度(高度) 层序编号 有序、无序 森林 5.1.2 的抽象数据类型定义 5.1.3的遍历操作 1、前序遍历 的前序遍历操作定义为: 若为空,则空操作返回;否则 (1)访问根结点 (2)按照从左向右的顺序前序遍历根结点的每一棵子。 2、中序遍历 的中序遍历操作定义为: 若为空,则空操作返回;否则 (1)按照从左向右的顺序后序遍历根结点的每一棵子; (2)访问根结点。 3、层序遍历 的层序遍历也称作的广泛遍历,其操作定义为的第一层开始,自上而下逐层遍历,在同一层中,按从左向右的顺序对结点逐个访问。 5.2的存储结构 5.2.1 双亲表示法 由的定义可知,中每个结点都有且仅有一个双亲结点。所以利用这一特性,可以用一维数组来存储各个结点,数组中一个元素对应一个结点,数组元素包括中结点的数据信息以及该结点的双亲在数组中的下标。 其中: Data为数据域,存储中结点的数据信息; Parent为指针即游标,存储该结点的双亲在数组中的小标。 5.2.2孩子表示法 1、多重链表表示法 (1)指针域的个数等于该结点的度。 (2)指针域的个数等于的度。 2、孩子链表表示法 把孩子看成一个线性表,且以单链表存储,称为该结点的孩子链表。则n个结点有n个孩子链表。 孩子节点有两类:孩子节点、表头结点。 5.2.3 双亲孩子表示法 即将双亲表示法和孩子链表表示法相结合的存储方法。仍将各结点的孩子分别组成单链表,同时用一维数组顺序存储中的各结点,数组元素除了包括结点的数据信息和该结点的孩子链表的头指针之外,还增设一个域存储该结点的双亲在数组的下标。 5.2.4孩子兄弟表示法 又称二链表表示法,其方法是链表中每个结点除数据域外,还设置了两个指针分别指向该结点的第一个孩子和右兄弟链表的结构: Firstchild data rightsib 指针域,存储第一个孩子结点的存储地址 数据域,存储该结点的数据信息 指针域,存储该结点右兄弟结点的存储地址 5.3二叉树的逻辑结构 最简单的结构,特别适合计算机处理,而且任何数都可以简单的转换二叉树。(重点内容) 5.3.1二叉树的定义 二叉树是n(n>=0)个结点的有限集合,该集合或者为空集,或者有一个根节点和两棵互不相交的、分别称为根节点的左子和右子二叉树组成。 二叉树具有五种基本形态: 1、空二叉树; 2、只有一个根结点; 3、根结点只有左子; 4、根结点只有右子; 5、根结点既有左子又有右子 特殊二叉树: 1、斜; 2、满二叉树; 3、完全二叉树; 5.3.2二叉树的基本性质 性质5-1 二叉树的第i层上最多有2^(i-1)个结点(i>=1)。 性质5-2 在一棵深度为k的二叉树中,最多有2^k-1个结点,最少有k个结点。 性质5-3 在一棵二叉树中,如果叶子结点的个数为n0,度为2的结点个数为n2,则n0=n2+1. 性质5-4 具有n个结点的完全二叉树的深度为【log2^n】+1。 性质5-5 对一棵具有n个结点的完全二叉树中的结点从一开始按层序编号,则对于任意的编号为i(1<=i<=n)的结点,有: (1)如果i>1,则结点i的双亲的编号为【i/2】;否则结点i是根结点,无双亲。 (2)如果2i<=n,则 结点i的左孩子的编号为2i;否则结点i无左孩子。 (3)如果2i+1<=n,则结点i的右孩子的编号为2i+1,否则结点i无右孩子。 5.3.3 二叉树的抽象数据类型定义 同类似,在不同的应用中,二叉树的基本操作不尽相同。 5.3.4 二叉树的遍历操作 二叉树的遍历是指从根节点出发,按照某种次序访问二叉树是所有结点,使得每个结点被访问一次且仅被访问一次。由于二叉树中每个结点都可能有两个子,因此需要寻找一条合适的搜索路径。 1、前序遍历 前序遍历二叉树操作定义为: 若为空,则空操作返回;否则 (1)访问根结点 (2)前序遍历根结点的左子 (3)前序遍历根结点的右子 2、中序遍历 中序遍历二叉树操作定义为: 若为空,则空操作返回;否则 (1)中序遍历根结点的左子 (2)访问根结点 (3)中序遍历根结点的右子 3、后序遍历 后序遍历根结点的左子 后序遍历根结点的右子 访问根结点 4、层序遍历 二叉树的层序遍历是指从二叉树的第一层开始,从上之下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。 5.4 二叉树存储结构及实现 5.4.1 顺序存储结构 具体步骤: (1)将二叉树按完全二叉树编号。 (2)将二叉树中的结点一编号顺序存储到一维数组中。 5.4.2 二叉链表 基本思想: 令二叉树的每个结点对应一个链表结点,链表结点除了存放于二叉树结点有关的数据信息外,还要设置指示左右孩子的指针。 5.4.3 叉链表 在二叉链表存储方式下,从某个结点出发可以直接访问它的孩子结点,但要找到它的双亲结点,则需要从根节点开始搜索,最坏的情况下,需要遍历整个二叉链表。此时采用链表储存二叉树。 其中,data,lchild,rchild个域的含义同二叉树,parent域为指向该结点的双亲结点指针。 5.4.4 线索链表 按照某种遍历次序对二叉树进行遍历,可以把二叉树中所有结点排成一个线性序列。在集体应用中,有时需要访问二叉树中的结点在某种遍历序列中前驱和后继,此时,在存储结构中应该保存结点在某种遍历序列中的前驱和后继信息。 前驱和后继结点的指针称为线索,加上线索的二叉树称为线索二叉树,加上线索的二叉链表称为线索链表。 5.5 二叉树遍历的非递归算法 5.5.1 前序遍历非递归算法 关键:在前序遍历过某个左子后,如何找到该结点的右子的根指针。 一般的前序遍历执行过程中,设要遍历二叉树的根指针为bt,可能出现两种情况: (1)若bt!=NULL,则表明当前二叉树不为空,此时,应输入根结点bt的值并将bt保存到栈中,准备继续遍历bt的左子。 (2)若bt=NULL,则表明以bt为根指针的二叉树遍历完毕,并且bt是栈顶指针所指结点的左子,若栈不空,则应根据栈顶指针所指结点找到待遍历右子的根指针并赋予bt,以继续遍历下去;若栈空,则表明整个二叉树遍历完毕。 5.5.2 中序遍历非递归算法 此算法只是需要将前序遍历的非递归算法中输出的语句cout<<bt->data移到bt=s[top--]之后即可。 5.5.3 后序遍历非递归算法 后序遍历的不同在于:结点要出入两次栈,出两次栈,这种情况的含义和处理方法为: (1)第一次出栈:只遍历晚左子,右子尚未遍历,则该结点不出栈,利用栈顶结点找到它的右子,准备遍历它的右子。 (2)第二次出栈:遍历完右子,该结点出栈,并访问它。 设根指针为bt,则可能有以下两种情况: (1)若bt!=NULL,则bt及标志flag入栈,遍历其左子。 (2)若bt=NULL,此时栈空,则整个遍历结束;若栈不空,则表明栈顶结点的左子或右子已遍历结束。若栈顶点的标志flag=1,则表明栈结点的左子已遍历完毕,将flag修改为2,修改为2,并遍历栈定点的右子;若栈顶结点的标志flag=2,则表明栈结点的右子也遍历完毕,输出栈顶结点。 5.6 森林二叉树转换 1.转换二叉树 将一棵转换二叉树的方法为: (1)加线——中所有相邻的兄弟结点之间加一条线; (2)去线——对中的每个节点,只保留它与第一个孩子结点之间的连线,删去它与其他孩子结点之间的连线。 (3)层次调节——以根结点为轴心,将顺时针转动一定角度,使之层次分明。 2.森林转换二叉树 (1)将森林中的每一棵二叉树转化二叉树; (2)从第二课二叉树开始,依次把后一棵二叉树的根结点作为一棵二叉树根节点的右孩子,当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。 3、二叉树转换森林 (1)加线——若某个结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……,都与结点y用线连起来; (2)去线——删去原二叉树中所有的双亲结点与右孩子结点的连线; (3)层次调整——整理由(1)、(2)两步所得到的森林,使之层次分明。 (4)森林的遍历 两种遍历方法;前序遍历后续遍历。 5.7 应用举例 5.7.1 二叉树的应用举例——哈夫曼及哈夫曼编码 1、哈夫曼也称最优二叉树,在实际中有着广泛的应用。 叶子节点的权值 是对叶子结点赋予的一个有意义的数值量。 二叉树的带权路径长度 设二叉树具有n个带权值的叶子节点,从根节点到叶子节点的路径长度与相应的叶子节点权值的乘积之和叫做二叉树的带权路径长度,记为: WPL=EWkLk 哈夫曼 给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,将其中带权值路径长度最小的二叉树称为哈夫曼。 哈夫曼算法基本思想: (1)初始化:由给定的n个权值构造n棵只有一个根结点的二叉树,从而得到一个二叉树集合。 (2)选取与合并:在F中选取根结点的权值最小的两棵二叉树分别作为左、右子构造一棵新的二叉树,这棵新的二叉树的根结点的权值为其左右子根结点的权值之和。 (3)删除与加入:在F中删除作为左、右子的两棵二叉树,并将新建的二叉树加入到F中。 (4)重复(2)(3)两步的操作,当集合F只剩下一棵二叉树时这棵二叉树便是哈夫曼。 2、哈夫曼编码 在进行程序设计时,通常给每一个字符记一个单独的代码来表示一组字符,我们称之为编码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何为xl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值