哈夫曼树及其应用(文件压缩)

哈夫曼树概念

先经过一个小例子来引出哈夫曼树,例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80~89分: B,70~79分: C,60~69分: D,<60分: E。bash

编制一个程序,将百分制转换成五个等级输出

if (a < 60){
    b = "E";
}
else if (a < 70) {
    b = "D";
}
else if (a<80) {
    b = "C";
}
else if (a<90){
    b = "B";
}
else {
  b = "A";
}
复制代码

若考虑上述程序所耗费的时间,就会发现该程序的缺陷。在实际中,学生成绩在五个等级上的分布是不均匀的。当学生百分制成绩的录入量很大时,上述断定过程须要反复调用,此时程序的执行效率将成为一个严重问题。编码

上述判断方式对应的判别树以下:spa

若是学生的总成绩数据有10000条,则5%的数据需 1 次比较,15%的数据需 2 次比较,40%的数据需 3 次比较,40%的数据需 4 次比较

所以 10000 个数据比较的 次数为: 10000 (5%+2×15%+3×40%+4×40%)=31500次设计

再看另外一种判断方式:3d

此种形状的二叉树,须要的比较次数是: 10000 (3×20%+2×80%)=22000次

显然:两种判别树的效率是不同的。code

哈夫曼树定义:在权为w1,w2,…,wn的n个叶子结点的全部二叉树中,带权路径长度WPL最小的二叉树称为赫夫曼树或最优二叉树。cdn

带权路径长度的最优值叫作WPL也就是上述例子的判断总次数31500次或者22000次 blog

其中,n表示叶子结点的数目,wi和li分别表示叶子结点ki的权值和树根结点到叶子结点ki之间的路径长度。 也就是上述例子的wi==这个结果的次数,li==须要判断的次数。

哈夫曼树的构造

构造规则:string

  1. 根据给定的n个权值{w1,w2,…,wn}构成二叉树集合F={T1,T2,…,Tn},其中每棵二叉树Ti中只有一个带权为wi的根结点,其左右子树为空.
  2. 在F中选取两棵根结点权值最小的树做为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左右子树根结点的权值之和.
  3. 在F中删除这两棵树,同时将新的二叉树加入F中.
  4. 重复二、3,直到F只含有一棵树为止.(获得哈夫曼树)

例:有4 个结点 a, b, c, d,权值分别为 7, 5, 2, 4,构造哈夫曼树。it

根据给定的n个权值{w1,w2,…,wn}构成二叉树集合F={T1,T2,…,Tn}

在F中选取两棵根结点权值最小的树做为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左右子树根结点的权值之和. 在F中删除这两棵树,同时将新的二叉树加入F中.

重复,直到F只含有一棵树为止.(获得哈夫曼树)

哈夫曼应用--文件压缩

哈夫曼编码

哈夫曼树的应用很广,哈夫曼编码就是应用之一。

等长编码

例:若是需传送的电文为 ‘ABACCDA’,它只用到四种字符,用两位二进制编码即可分辨。假设 A, B, C, D 的编码分别为 00, 01,10, 11,则上述电文便为 ‘00010010101100’(共 14 位),译码员按两位进行分组译码,即可恢复原来的电文。 这种编码的特色是译码简单且具备惟一性,但编码长度并非最短的。

不等长编码

在传送电文时,为了使其二进制位数尽量地少,能够将每一个字符的编码设计为不等长的,使用频度较高的字符分配一个相对比较短的编码,使用频度较低的字符分配一个比较长的编码。例如,能够为A,B,C,D四个字符分别分配0,00,1,01,并可将上述电文用二进制序列:000011010发送,其长度只有9个二进制位,但随之带来了一个问题,接收方接到这段电文后没法进行译码,由于没法判定前面4个0是4个A,1个B、2个A,仍是2个B,即译码不惟一,所以这种编码方法不可以使用。

所以,为了设计长短不等的编码,以便减小电文的总长,还必须考虑编码的惟一性,即在创建不等长编码时必须使任何一个字符的编码都不是另外一个字符的前缀,这宗编码称为前缀编码(prefix code)利用哈夫曼树来实现

用二叉树设计二进制前缀编码

以电文中的字符做为叶子结点构造二叉树。而后将二叉树中结点引向其左孩子的分支标 ‘0’,引向其右孩子的分支标 ‘1’; 每一个字符的编码即为从根到每一个叶子的路径上获得的 0, 1 序列。如此获得的即为二进制前缀编码。

编码: A:0, C:10,B:110,D:111

任意一个叶子结点都不可能在其它叶子结点的路径中。

哈夫曼编码实例

好比有ABCDEF六个字母,经过0和1编码用二进制字符发送。普通编码后的数据为000001010011100101,解码的时候能够按照3位一份来解码。 假设ABCDEF出现的几率分别为27%、8%、15%、15%、30%、5%。则造成的赫夫曼树以下图。此外咱们能够将左右分支分别改成0和1,而后用0和1来编码字母。

则编码结果为 A=0一、B=100一、C=10一、D=00、E=十一、F=1000。

本来的编码结果为:000001010011100101
如今的编码结果为: 0110011010011100
复制代码

如今的编码结果明显要比以前的少了一些,短短是几个字母编码后,少的量不是很大,若是是通篇的文章或更多,那么编码量将会节省不少,这就是文件压缩的原理。而且随着字符的增多,按照权重优先级编码,这种压缩会进一步提高不少。

相关文章
相关标签/搜索