【扫盲】---哈夫曼编码&哈夫曼树

以前学过的知识都没啥印象了,再次记录一下。

哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,是一种统计编码方式,属于无损压缩编码。哈夫曼编码是变长编码,对于出现频率高的信息,编码长度较短,出现频率低的信息,编码长度较长。这样处理全部信息的总码长一定小于实际信息的符号长度。有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。

哈夫曼编码,主要目的是根据使用频率来最大化节省字符(编码)的存储空间。

比如我们有一段文字“BADCADFEED”,显然用二进制数字(0和1)表示是很自然的想法。

这样真正传输的数据就是“001000011010000011101100100011”,对方接收时同样按照3位一组解码。如果一篇文章很长,这样的二进制串也非常的可怕。而且事实上,每个字母或者汉子的出现频率是不同的。

å¾ç¤º

假设六个字母的频率为A 27,B 8, C 15, D 15 , E 30, F 5,合起来正好是100%,那就意味着我们完全可以用哈夫曼树来规划它们。

左图为构造哈夫曼树的过程的权值显示。右图为将权值左分支改为0,右分支改为1后的哈夫曼树。

å¾ç¤º

我们对这六个字母用其从树根到叶子所经过的路径的0或1来编码,可以得到下表:

å¾ç¤º

å¾ç¤º

也就是说我们的数据被压缩了,节约了大概17%的存储或传输成本。随着字符的增加和多字符权重的不同,这种压缩会更显出优势来。

接收到哈夫曼编码后应该如何解码呢?
仔细观察上面的赫夫曼编码表中各个字母的编码会发现,不存在容易与1001、1000混淆的10、100等编码。这就说明若要设计长短不等的编码,则必须是任一字符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码

可仅仅是这样不足以让我们去方便的解码,因此解码时,还是要用到哈夫曼树,即发送方和接收方必须约定好同样的哈夫曼编码规则。

 


哈夫曼编码步骤:

①概率统计(如对一幅图像或者m幅同种类型图像作灰度统计),得到n个不同概率的信息符号;

②将信号源的符号按照出现概率递减的顺序排列;

③在信源符号中选择概率最小的两个,将他们的概率相加,计算结果作为其合事件(新符号)的出现概率。在合并运算时,概率大的符号用编码0表示,概率小的符号用编码1表示;

④这时概率的个数减为n-1个,将这n-1个概率,按从大到小的顺序排序;

⑤重复③,将新排序后的最后两个小概率再相加,计算合事件的概率,如此反复重复n-1次,只带概率相加的结果为1为止;

⑥记录下概率为1处到当前信号源符号之间的0,1序列,从而得到每个符号的编码,构成霍夫曼码字,到此编码结束。

 

简易的理解就是,假如我有A,B,C,D,E五个字符,出现的频率(即权值)分别为5,4,3,2,1,那么我们第一步先取两个最小权值作为左右子树构造一个新树,即取1,2构成新树,其结点为1+2=3,权重大的符号用1表示,权重小的符号用0表示,如图:

è¿éåå¾çæè¿°

虚线为新生成的结点,第二步再把新生成的权值为3的结点放到剩下的集合中,所以集合变成{5,4,3,3},再根据第二步,取最小的两个权值构成新树,如图: 

è¿éåå¾çæè¿°


再依次建立哈夫曼树,如下图:

è¿éåå¾çæè¿°

其中各个权值替换对应的字符即为下图:

è¿éåå¾çæè¿°

所以各字符对应的编码为:A->11,B->10,C->00,D->011,E->010 


霍夫曼编码是一种无前缀编码。解码时不会混淆。其主要应用在数据压缩,加密解密等场合。

如果考虑到进一步节省存储空间,就应该将出现概率大(占比多)的字符用尽量少的0-1进行编码,也就是更靠近根(节点少),这也就是最优二叉树-哈夫曼树。

哈夫曼树

哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+…+ Wn*Ln),N个权值Wi(i=1,2,…n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,…n)。可以证明哈夫曼树的WPL是最小的。 
构造哈夫曼树的算法如下: 
1)对给定的n个权值{W1,W2,W3,…,Wi,…,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,…,Ti,…, Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。 
2)在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。 
3)从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。 
4)重复2)和3),直到集合F中只有一棵二叉树为止。

哈夫曼树的应用场景


其实赫夫曼树使用场景还真不少,例如apache负载均衡的按权重请求策略的底层算法、咱们生活中的路由器的路由算法、利用哈夫曼树实现汉字点阵字形的压缩存储

 

参考:

https://blog.csdn.net/qq_36653505/article/details/81701181

https://blog.csdn.net/u011507175/article/details/64920643

https://blog.csdn.net/qq_28602957/article/details/71036402

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章