数据结构学习笔记——哈夫曼树

简介: 数据结构学习笔记——哈夫曼树

一、路径、路径长度、权值


1、路径和路径长度


在树中,一个结点和另一个结点之间的分支即为这两个结点之间的路径;路径长度即为树中路径上的分支数目,即路径上所经过的边的个数。

树的路径长度等于根结点到树中每个结点的路径长度之和。

2、权值


为树中每个叶子结点(度为1的结点)赋予一个数值,则该值称为叶子结点的权值,简称为权。

1667294112450.jpg


3、带权路径长度

(1)叶子结点的带权路径长度


叶子结点的权值与树的根结点到该叶子结点之间的路径长度的乘积称为叶子结点的带权路径长度。

例如上图二叉树中,叶子结点D的权值为4,根结点A到结点D的分支数目为2,所以该叶子结点的带权路径长度为4×2=8。


(2)树的带权路径长度(WPL)


树中所有叶子结点的权值乘以该结点的路径长度之和即为树的带权路径长度(WPL)。

例如上图二叉树中,该二叉树的带权路径长度为:

WPL=4×2+2×2+3×2+3×2=24。


二、哈夫曼树的构造


哈夫曼树的构造步骤如下:


例如,给定一组权值为{2,3,6,7},构造哈夫曼树并求其带权路径长度。


1、首先选取两棵根结点权值最小的树作为左、右子树,新的二叉树的根结点权值为其权值之和,然后将原先两个结点从森林中删除,新的结点添加进去。

2+3=5,相加后将这两个删除后,将5添加,如下图:

1667294141939.jpg

2、重复步骤1,继续选择两个权值最小的结点进行构造,然后将其从森林中删除,并将新的结点添加。

5+6=11,相加后将这两个删除后,将11添加,如下图:

1667294152498.jpg

这样,就完成了由四个带权叶子结点构造成的哈夫曼树,如下:

1667294171361.jpg

其带权路径长度为:WPL=7×1+6×2+3×3+2×3=34。

注:通过一组权值构造出来的哈夫曼树不唯一,这是由于,每次选定权值最小的两棵树时,左右子树并没有限制,从而使构造出来的哈夫曼树不唯一,哈夫曼树具有最小的带权路径长度,即其WPL是最小的。

1667294178682.jpg

其带权路径长度为:WPL=6×2+2×3+3×3+7×1=34。


例如,给定一组权值为{3,5,6,9,12},构造哈夫曼树并求其带权路径长度。

1667294187061.jpg

1667294199237.jpg


由于上面的构造方式,必然会使路径长度最大,从而导致WPL最大,不是哈夫曼树。

故以下这种构造方式是正确的,这是由权值为{3,5,6,9,12}与之对应的哈夫曼树:

1667294207620.jpg


例如,给定一组权值为{10,12,16,21,30},构造哈夫曼树并求其带权路径长度。

1667294219648.jpg

1667294231771.jpg

1667294246713.jpg


三、哈夫曼树的定义


哈夫曼树是一种特殊的二叉树(其中哈夫曼二叉树是哈夫曼n叉树的一种,以下都以哈夫曼二叉树为例),树中所有叶子结点都带有权值,带权路径长度最小的二叉树称为哈夫曼树,也称为最优二叉树,哈夫曼树中只有度为0和2的结点,不存在度为1的结点。

哈夫曼树既不是满二叉树,也不是完全二叉树,只是一棵二叉树。


通过哈夫曼树的定义,可以得到哈夫曼树中,两个权值最小的结点一定是兄弟结点,另外哈夫曼树中,任意一非叶子结点的权值不小于其下一层的任意一结点的权值。


四、哈夫曼树的性质


✨若有n个结点,则在哈夫曼树的构造过程中,新建了n-1个结点,最终所得到的结点总数为2n-1。

✨由于哈夫曼树只有度为0和2的结点,不存在度为1的结点,即n=n0+n2,且又由二叉树的性质,叶子结点数等于度为2的结点数加1(n0=n2+1),故从而可以求得哈夫曼树的叶子结点数和度为2的结点数。

例、一棵哈夫曼树中含有215个结点,对其进行哈夫曼编码,求可以得到多少个不同的码字。

解:由于是求得到多少个不同的码字,根据哈夫曼编码的构造,可知针对的是叶子结点,所以求叶子结点,由n=n0+n2=215,且n0=n2+1,可解得:n0=(n+1)/2=(215+1)/2=108,

故可以得到108个不同的码字。


例、对于n个互不相同的符号进行哈夫曼编码,若生成的哈夫曼树共有115个结点,求n的值。

解:这里求n的值,也是求叶子结点,由115=n0+n2,且n0=n2+1,可解得:n0=58。


✨在二叉树中,n为结点总数,分支总数=n-1=n1+2n2,而对于哈夫曼树,分支总数=n-1=2n2,即结点个数为N的哈夫曼树有N-1条分支,设叶子结点为n0,由n=n0+n2,则非叶子结点(度为2的结点)的个数为n2=n0-1。

✨同理,可以得到在度为m的哈夫曼树中,设叶子结点为n0,则非叶子结点的个数为

⌈ (n0-1)/(m-1) ⌉。


五、前缀编码


在对字符集进行编码时,若字符集中任一字符的编码都不是其它字符的编码的前缀,则称这种编码为前缀编码。


例如,字符集{00,10,11},其中任一字符的编码都不是其它字符的编码的前缀,这是前缀编码;


例如,字符集{10,11,100,101,110},其中字符10是字符100、字符101的前缀,,字符11是字符110的前缀,所以不是前缀编码。


六、固定/可变长度编码


哈夫曼编码是一种可变长度编码,以下介绍固定/可变长度编码。


(一)固定长度编码


若对每个字符使用相同长度的二进制信息进行编码,则这种编码称为固定长度编码,简称为定长编码。


(二)可变长度编码(哈夫曼编码)


与固定长度编码相反,可变长度编码使用不等长的二进制信息进行编码,可变长度编码可以使字符的平均编码长度缩短,从而更好地压缩数据进行传输。


哈夫曼编码是一种可变长度编码,它根据字符出现的概率来构造编码,规定一个编码不能是其它编码的前缀。

求哈夫曼编码是在建立好的哈夫曼树上,从树中每个叶子结点开始,沿着双亲一直向上到根结点,每向上一步,就走过了哈夫曼树的一个分支,即得到一位哈夫曼码值,开始得到的是最终编码的低位,然后是高位。


简单的来说,在哈夫曼编码中,字符的编码为根结点到该字符的路径上的边所标记的序列,规定左分支代表“0”,右分支代表“1”,从根结点到每个叶子结点所经过的路径分支所组成的0与1序列即为该结点对应字符的编码,各个字符出现的频度作为结点的权值,如下对该哈夫曼树进行编码:

1667294297169.jpg

可以得到叶子结点的哈夫曼编码为:

1667294307695.jpg

由于哈夫曼树不唯一,所以得到的哈夫曼编码也不唯一,如下:

1667294317333.jpg

相关文章
|
7月前
|
存储 算法 C语言
C语言---数据结构实验---哈夫曼树及哈夫曼编码的算法实现---图的基本操作
C语言---数据结构实验---哈夫曼树及哈夫曼编码的算法实现---图的基本操作
|
6天前
|
编译器
【数据结构】哈夫曼树编译码器【课程设计】
【数据结构】哈夫曼树编译码器【课程设计】
|
6天前
|
算法 Java
数据结构-构造哈夫曼树【详解+代码+图示】一文解惑!
数据结构-构造哈夫曼树【详解+代码+图示】一文解惑!
460 0
【数据结构】我的学习笔记-二叉树
【数据结构】我的学习笔记-二叉树
|
8月前
|
存储 算法 关系型数据库
|
8月前
|
机器学习/深度学习 存储 算法