数据结构论坛

首页 » 分类 » 分类 » Python数据结构树五
TUhjnbcbe - 2020/12/4 16:27:00
白癜风什么不能吃 http://m.39.net/pf/a_7485587.html

00

前言

前面对树已经介绍了不少相关内容,从一棵普通的多叉树到二叉树,再到二叉搜索树,最后到上一篇推文的平衡二叉搜索树(AVL树),而本文打算就之前了解过的内容进行一些知识上的补充,主要按照大学数据结构课程考试要求的内容进行补充,对这部分内容感兴趣的读者可以了解下。

本文只介绍一些知识点,内容不多,本文无任何代码部分。主要内容为

补充森林这一概念

二叉树表示森林与树

森林与树的遍历

Huffman树

01

森林

这里补充一个森林的概念

m(m≥0)棵互不相交的树的集合

直接放示意图,看图就能理解了,图中四棵树组成森林。

02

二叉树表示森林与树树→二叉树

用二叉树表示一棵树的方法,也称孩子兄弟表示法

一棵二叉树根结点的左子结点是它的第一个子结点,右子结点是它的下一个兄弟结点。

我们知道二叉树的每一棵子树也都是二叉树,所以它的每一棵子树也都遵循上述规定。

由这一规定我们可以知道,从整体来看,这棵二叉树必定没有右半支,即根结点没有右子结点,理由也很简单,根结点没有兄弟结点。

直接用示意图举例,转换过程按照规定进行,不难。

森林→二叉树

刚才介绍的树到二叉树的转换,转换结果是没有右半支的,而森林转换为二叉树,如果森林中不止一棵树,那么转换结果是有右半支的。

先将森林中的每一棵树单独转换成二叉树,第一棵树的右子结点为第二棵树的根结点,第二棵树的右子结点为第三棵树的根结点,依此类推。

也很简单,不多解释,直接看示意图。图中用颜色对两棵树进行了区分。

二叉树→树、森林

由二叉树恢复为树或森林,步骤与上述步骤正好相反,读者可用上面提供的两个示意图进行练习,这里不再过多解释。

03

森林与树的遍历

我们先回顾下二叉树的三种遍历方式。详细解释查看推文《Python数据结构——树(二)》

先序遍历:根、左、右

中序遍历:左、根、右

后序遍历:左、右、根

树的遍历

仿照这三个遍历,我们可以写出树的遍历如下。

先序遍历:先遍历根结点,再遍历所有子结点。

中序遍历

后序遍历:先遍历所有子结点,后遍历根结点。

这里我们说的树是普通的树,也就是多叉树,关于多叉树的中序遍历,由于子结点之间不分左右子结点,无法确定在访问完哪一个子结点后对根结点进行访问,然后再访问剩下的子结点,所以没有中序遍历。

补充内容如下

树的先序遍历结果,与树转换成二叉树后的先序遍历结果相同。

树的后序遍历结果,与树转换成二叉树后的中序遍历结果相同。

森林的遍历

森林的遍历总结如下

先序遍历:与森林转换成的二叉树的先序遍历结果相同。

中序遍历:与森林转换成的二叉树的中序遍历结果相同。

后序遍历:森林无后序遍历。

补充

一棵二叉树的先序遍历与中序遍历可以唯一确定这棵二叉树。

一棵二叉树的后序遍历与中序遍历可以唯一确定这棵二叉树。

上面两句话在前一篇推文有提到过,当时是用于验证最终生成的二叉树是否为AVL树。只需要把先序遍历与中序遍历结果输出,还原成一棵二叉树,再与我们手动构造的结果进行比对即可。

那么问题来了,为什么知道先序遍历与中序遍历,或后序遍历与中序遍历就可以唯一确定一棵二叉树呢?就算能够唯一确定一棵二叉树,又该如何由这两个遍历结果还原成二叉树呢?

先解决第一个问题,证明方法是数学归纳法,设二叉树有n个结点。证明步骤如下:

已知后序序列与中序序列,可以唯一确定一棵二叉树,证明步骤与上述步骤类似,不再证明。

接下来解决第二个问题,已知先序序列与中序序列如何还原成一棵二叉树。

还原过程其实与上述证明过程类似。

找出中序序列中与先序序列第一个元素相同的元素,作为根结点。

中序序列中位于根结点左侧的是左子树,位于根结点右侧的是右子树。

若左子树有k个结点,在先序序列中除根结点外的前k个结点构成左子树,其余结点构成右子树。

对每一棵子树重复执行上述步骤,直至还原出一棵完整的二叉树。

还原过程示意图如下。

另外,只知道先序序列和后序序列是无法唯一确定二叉树的。

04

Huffman树

Huffman树又称最优二叉树。

先介绍几个概念。

结点路径:从树中一个结点到另一个结点,之间的分支构成这两个结点之间的路径。

路径长度:结点路径上的分支数目。

树的路径长度:从树根到每一个结点的路径长度之和。

结点的带权路径长度:从该结点到树的根结点之间的路径长度乘以结点的权值。

树的带权路径之和:树中所有叶子结点的带权路径长度之和。

接下来介绍Huffman树的定义

具有n个叶子结点(每个结点的权值为wi)的二叉树不止一棵,但在所有的二叉树中,必定存在一棵带权路径长度最小的树,称这棵树为Huffman树(或最优树)

构建Huffman树过程。

将n个带权叶子结点{w1,w2,...,wn}作为树{T1,T2,...,Tn}

选取两棵权值最小的树作为左右子树,构建一棵新的二叉树,新二叉树的权值为左右子树权值之和

集合中移除这两棵子树,将新生成的二叉树添加进集合

重复步骤2、步骤3,直至集合中只剩下一棵树。

由于每次构造新二叉树时,两棵子树并没有规定哪一棵作为左子树,哪一棵作为右子树,所以最终会出现构造结果不唯一的情况。

在这里我们可以自己按照一定的规则构造,下面这条规则可以不遵守,仅是为结果更加规范。

以权值小的为左子树,权值相等时以深度小的为左子树。

构造过程示意图如下:

Huffman编码则是以字符集作为叶子结点,字符出现频度作为权值,构造生成一棵Huffman树,树的左分支代表“0”,右分支代表“1”,这样从根结点到叶子结点所经历的路径分支上的“0”和“1”组成的字符串,作为该叶子结点所代表的字符的编码。

在最后Lastbutnotleast

本文补充介绍了森林这一概念,同时介绍了如何用二叉树表示普通的树与森林,以及关于树和森林的遍历方法,在最后介绍了一种最优树——Huffman树。

文中内容以概念为主,内容并不难,难理解一点的地方也都有示意图辅助理解,有部分地方用到之前介绍过的概念,不太熟悉的读者可以点下方链接阅读往期关于树的推文。

往期精彩回顾

Python数据结构——树(二)

Python数据结构——树(三)

Python数据结构——树(四)

预览时标签不可点收录于话题#个上一篇下一篇
1
查看完整版本: Python数据结构树五