树的应用(赫夫曼树及其应用)

相关定义

赫夫曼树,又称最优树,是一类带权路径长度最短的树。以下仅限于讨论最优二叉树:
路径指的是从一个结点到另一个结点之间的连线。路径长度指路径上线段(两个相连结点之间的连接线段)的个数。树的路径长度指的是从树根到树中其余每个结点的路径长度之和。结点的带权路径长度为从树根到该结点之间的路径长度与该结点上所带权值的乘积。树的带权路径长度定义为树中所有叶子结点的带权路径长度之和。

假设有 n 个权值 {w1,w2,w3...wn},试构造一棵有n个叶子结点的二叉树,每个叶子结点的权值为 wi,显然构造出的二叉树很多。其中带权路径长度最小的二叉树称为最优二叉树或赫夫曼树

如何构造赫夫曼树

赫夫曼算法:
1.根据给定的 n 个权值{w1,w2,w3...wn} 建立 n 棵二叉树的集合 F={T1,T2,T3......Tn},其中每棵 Ti 树中只有一个带有权值为 wi 的根结点,左右子树为空。
2.在F中选择两个根结点权值最小的树作为左右子树的根结点,构成一棵二叉树,这棵二叉树的根结点的权值为其左右子树根结点上的权值之和。
3.在F中删除这两棵树,并将先前建立的这棵树加入F中。
4.重复2和3操作,直到F中只有一棵树为止。这棵树就是所求的赫夫曼树。

赫夫曼树的存储结构

由于赫夫曼树中没有度为1的结点,所以一棵含有 n 个叶子结点的赫夫曼树共有2n-1个结点,可以存储在一个大小为 2n-1 的一维数组中。为每个结点设置两个位置指示器,分别指示该结点的左右孩子结点在数组中的下标(位置)。存储结构定义如下:

//对于赫夫曼树中每个结点的定义
typedef struct {
	int weight;        //结点的权重
	int lchild, rchild;
}HTNode;
//对于赫夫曼树的定义
typedef struct {
	HTNode *HTree;   //动态分配数组存储树结点
	int root;   //根结点的位置
}HuffmanTree;

赫夫曼编码

传输文件时需要将文本信息转化成二级制数,每个字符都对应一个二进制数。为了压缩信息,需要对这些字符设计对应的不等长编码。使用频率高的字符对应的二进制码最短,使用频率最低的字符对应的二进制码最长。同时,必须任意一个字符的编码都不是另一个字符的编码的前缀,这种编码称为前缀编码

利用二叉树可以设计二进制的前缀编码。假设一棵二叉树,叶子结点代表字符,约定左分支表示字符0,右分支表示字符1,则可以从根结点到叶子结点的路径的分支上的字符组成的字符串作为该叶子结点字符的编码。如此得到的编码必为二进制前缀编码。由此可见,对于一篇电文,只需要统计每种字符在电文中出现的次数,依次作为权值,将每种字符设计成叶子结点,建立赫夫曼树,由此得到的二进制前缀编码便称为赫夫曼编码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值