哈夫曼树及其应用

哈夫曼树的基本概念

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

结点的路径长度:两结点间路径上的分支数

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

权(weight):将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权

结点的带权路径长度:从结点到该结点之间的路径长度与该结点的乘积

树的带权路径长度:树中所有叶子结点的带权路径长度之和
在这里插入图片描述
结点的路径长度:
在这里插入图片描述
树的路径长度:
在这里插入图片描述
结点数目相同的二叉树中,完全二叉树路径长度最短的二叉树

树的带权路径长度:
在这里插入图片描述
哈夫曼树:最优树 || 带权路径长度(WPL)最短的树
注:“带权路径长度最短”是在“度相同”的树中比较而得的结果,因此有最优二叉树、最优三叉树之称等等。

在这里插入图片描述
我们发现:

  • 满二叉树不一定是哈夫曼树
  • 哈夫曼树中权越大的叶子离根越近
  • 具有相同带权结点的哈夫曼树不唯一

哈夫曼树的构造算法

哈夫曼算法(构造哈夫曼树的方法)
①根据 n 个给定的权值{W1,W2,…,Wn}构成 n 棵二叉树的森林 F={T1,T2,…,Tn},其中 Ti 只有一个带权为 Wi 的根结点
巧记:构造森林全是根

②在 F 中选取两棵根结点的权值最小的树作为左右子树,构造一棵新的二叉树,且设置新的二叉树的根结点的权值为其左右子树上根结点的权值之和
巧记:选用两小造新树

③在 F 中删除这两棵树,同时将新得到的二叉树加入森林中
巧记:删除两小添新人

④重复②和③,直到森林中只有一棵树为止,这棵树即为哈夫曼树
巧记:重复②、③剩单根
在这里插入图片描述
我们发现:
①哈夫曼树的结点的度为0或2,没有度为1的结点
②包含 n 个叶子结点的哈夫曼树中共有 2n-1 个结点
(因为包含 n 棵树的森林要经过 n-1 次合并才能形成哈夫曼树,共产生 n-1 个新结点,所以 n+n-1=2n-1)
在这里插入图片描述
总结:
1、在哈夫曼算法中,初始时有 n 棵二叉树,要经过n-1次合并最终形成哈夫曼树
2、经过 n-1 次合并产生 n-1 个新结点,且这 n-1 个新结点都是具有两个孩子的分支结点


哈夫曼树算法实现

采用顺序存储结构—— 一维结构数组
结点类型定义

typedef struct
{
   int weight;
   int parent,lch,rch;
}HTNode,*HuffmanTree;   

在这里插入图片描述
在这里插入图片描述
例:有 n=8,权值为 W={7,19,2,6,32,3,21,10}的根结点,构造哈夫曼树
在这里插入图片描述
构造后:
在这里插入图片描述
算法步骤:
1、初始化 HT[1…2n-1]:lch=rch=parent=0;
2、输入初始 n 个叶子结点:置 HT[1…n]的weight值
(HT就是上图左边的结构数组)
在这里插入图片描述
3、进行以下 n-1 次合并,依次产生 n-1 个结点 HT[i],i=n+1…2n-1:
①在 HT[1…i-1]中选出两个未被选过(parent==0的结点)的 weight 最小的两个结点 HT[s1] 和 HT[s2],s1、s2为两个最小结点下标;
②修改 HT[s1] 和 HT[s2] 的parent值:HT[s1].parent=i;HT[s2].parent=i;
③修改新产生的 HT[i]:

  • HT[i].weight = HT[s1.weight] + HT[s1.weight];
  • HT[i].lch = s1;HT[i].rch = s2;
    在这里插入图片描述

哈夫曼编码思想

在远程通讯中,要将待传字符串转换成二进制的字符串

将编码设计为长度不等的二进制编码,即让待传字符串中出现次数较多的字符采用尽可能的编码,则转换的二进制字符串便可能减少
在这里插入图片描述
问题:什么样的前缀码能使得电文总长最短?

——哈夫曼编码
在这里插入图片描述
举个例子:
在这里插入图片描述
两个问题:
1、为什么哈夫曼编码能够保证是前缀编码?
答:因为没有一片树叶是另一片树叶的祖先,所以每个叶结点的编码就不可能是其他叶结点编码的前缀

2、为什么哈夫曼树编码能够保证字符编码总长最短?
答:因为哈夫曼树的带权路径最短,故字符编码的总长最短

  • 性质1:哈夫曼编码是前缀码
  • 性质2:哈夫曼编码是最优前缀码

哈夫曼编码的算法实现

在这里插入图片描述


文件的编码和译码

1、编码
①输入各字符及其权值
②构造哈夫曼树——HT[i]
③进行哈夫曼编码——HC[i]
④查 HC[i],得到各字符的哈夫曼编码

2、解码
①构造哈夫曼树
②依次读入二进制码
③读入0,则走向左孩子;读入1,则走向右孩子
④一旦到达某叶子时,即可译出字符
⑤然后再从根出发继续译码

举个例子:
在这里插入图片描述


借鉴:青岛大学–王卓

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值