以下内容整理来源:zzu信息工程学院数据结构课件
本文对上一篇【搜索与图论】二叉树 内容做补充,包括:线索二叉树、树和森林的存储和遍历、树与二叉树与森林的转换、哈夫曼树和哈夫曼编码
1 线索二叉树
1.1 起因
我们无法直接得到结点在任意序列中的前驱和后继信息,这种信息只能在遍历的动态过程中才能得到。
在有n
个结点的二叉链表中必定存在n+1
个空链域,可用它们存放结点的前驱和后继。
引入线索二叉树的目的:充分利用二叉链表的空指针域,保存动态遍历过程中得到的结点前驱和后继的信息
1.2 定义和术语
举个例子:
1.3 遍历
二叉树的遍历分为先、中、后序,线索二叉树也是同理。
以先序为例:
中序和后序同理,直接给出结论:
此外,二叉树的中序、先序、后序的存储结构也有差异:
1.4 构造过程
在遍历时,其实已经给出了每种序列的构造过程了。
构造的实质就是:将二叉链表的空指针改为指向前驱或后继的线索。
而线索化的过程,就是在遍历过程中修改空指针使其指向某一遍历序列中的前驱结点或后继结点。设指针pre
始终指向刚刚访问过的结点,指针p
指向当前访问的结点,那么pre
始终指向p
的前驱。
以中序为例:
其实这个没有看太懂。二叉线索树确实没什么印象了……
2 树与二叉树的转换
2.1 树的存储结构
在介绍树与二叉树的转换之前,先介绍树的几种存储结构:(与二叉树的存储结构要区分开)
- 双亲表示法
- 多重链表表示法
- 孩子链表表示法
- 带双亲的孩子链表表示法
- 兄弟表示法
双亲表示比较好理解,就是(data, parent)
多重链表就是单链表的链表,对于每个单链表(一个结点一个单链表),根据存储信息的不同,又分为两种情况:
孩子链表法,构造方式如名字所说,有点像有向图的邻接表存储。
带双亲的孩子链表,综合了双亲表示法和孩子链表表示法的优点:找孩子方便,找爸妈也方便。
孩子兄弟表示法,这真的是碳基生物能想出来的表示方法么,虽然对树和二叉树的转换很有用……
孩子兄弟表示法这个比较抽象,举个例子:
2.2 树和二叉树的转换
树和二叉树的转换原理就是上面提到的孩子兄弟表示法。
2.2.1 树转换成二叉树
树转换成二叉树分三步走:加线、抹线、旋转
2.2.2 二叉树转换成树
也是三步走:加线、抹线、排列
2.3 树的遍历
二叉树的遍历分为先、中、后、层序四种,树的遍历是先、后、层。去掉了中序遍历。
但是,树的先序、后序对应的就是与其等价的二叉树的先序、后序吗?我们看一个例子:
树的遍历:
- 先序:ABEFGCDHI
- 后序:EFGBCHIDA
二叉树的遍历:
- 先序:ABEFGCDHI
- 中序:EFGBCHIDA
- 后序:GFEIHDCBA
可以发现,树遍历的先序、后序分别对应二叉树的先序、中序。并不是字面意思上的后序对后序。
3 树和森林
树和森林这里主要有两个:森林和二叉树的转换、森林的遍历。
3.1 森林和二叉树的转换
3.1.1 森林转二叉树
先熟悉转换规则,两步走:
- 树转换成二叉树
- 根相连(一个一个挂上去)
这里就是孩子兄弟表示法的优势所在了,因为经过孩子兄弟表示法不仅可以转换成二叉树,而且可以保证这样的二叉树的根结点没有右子树,从而让其他的二叉树挂上来。
举个例子:
3.1.2 二叉树转森林
原理一样,不多解释,怎么来就怎么倒回去。
3.2 森林的遍历
同样,我们给一个例子:
森林的遍历:
- 先根:ABCDEFGHIJ
- 中根:BCDAFEHJIG
二叉树的遍历:
- 先根:ABCDEFGHIJ
- 中根:BCDAFEHJIG
可以看出森林和二叉树的遍历从名字上看是对应的。其实在PPT中已经提到,森林的中根遍历就是对每一棵树的后根遍历,而树的后根遍历 = 二叉树的中根遍历。
最后我们得出,在遍历顺序中:
- 二叉树的先 = 树的先 = 森林的先
- 二叉树的中 = 树的后 = 森林的中
4 Huffman树与Huffman编码
4.1 术语和定义
下面是一个Huffman树(最优二叉树)的定义:
根据树的带权路径长度WPL
的定义,我们可以求出图中三棵树的WPL
分别是:
- (9 + 7 + 2 + 5) * 2 =
46
- 5 * 2 + 9 * 3 + 7 * 3 + 2 =
60
- 9 + 14 + 6 + 15 =
44
4.2 Huffman树的构造
在构造Huffman树时,我们只需要掌握原理就可以很快理解是怎样构造的了。
Huffman树要求是WPL
最小,因为权值是固定的,所以我们只需要让权值大的路径长度尽可能小,直观上讲就是让权值大的结点尽可能靠近根结点。这就是构造Huffman树的原理。
下面是具体的过程:
4.3 Huffmans树的算法实现
在编码时,我们首先要对数组初始化。给定n
个权值,也就是给定n
个叶子结点。那么这棵树中共有多少个结点?(也就是共开辟多少个数组单元)
观察Huffman树我们可以发现,Huffman树中要么是叶子结点,要么是出度为2的结点。(这类树又称严格二叉树或正则二叉树)
由n0 = n2 + 1可知,出度为2的结点共有:n-1
个。
所以结点总数N = 2n - 1
4.4 Huffman编码
Huffman树的应用包括:
- 高效解判定问题
- 在压缩编码领域的应用:Huffman编码
常见的编码方式如下:
其中,前缀编码指的是:任一字符的编码不是其他字符编码的前缀。
由前缀编码,我们引出Huffman编码:
编码方式就是字符按词频排序,将词频作为权值,利用权值进行Huffman编码。
这样编码既可以使编码不冲突(即任一编码都不是其他编码的前缀),又可以做到编码结果的平均长度最短(因为权值高的分配的码长短)。既保证了准确性,又提高了效率。Huffman编码nb