有趣的赫夫曼树

有趣的赫夫曼树

美国有个数学家叫赫夫曼,60年前他根据数据的使用概率,发明了一个二叉树叫赫夫曼树。

这个赫夫曼树被用在了数据压缩上,被称为赫夫曼编码,这是后来压缩的基础。

 

他解决的问题主要思想是:根据元素出现的概率,获得最优解。

 

举例如下:

学生考试成绩出来后,会根据考试成绩分等级,极优秀,优秀,中等,及格,不及格。如果我们按照普通逻辑进行判断时,通常是:

 

1

2

3

4

5

6

7

8

9

10

11

if (Score < 60) {

    printf("不及格");

else if (Score < 70) {

    printf("及格");

else if (Score < 80) {

    printf("中等");

else if (Score < 90) {

    printf("优秀");

else if (Score < 100) {

    printf("极优秀");

}

但是按照分数的分布概率,优秀:30%,中等:40%,及格:15%,极优秀:10%,不及格:5%

如果先判断优秀,中等,再判断极优秀,极优秀,不及格,则可以提高很多效率。

赫夫曼树就是根据概率来生成的二叉树。

转换成二叉树区别如下:

 

有趣的赫夫曼树

从根节点出发,遍历每一个叶子节点,是的到达节点时走的链接树乘以节点(nodeLinkNum * weight)对应的权重之和最小

如:

sum = 1*5+2*15+3*40+4*30+4*10

显然,左图和右图总和不一样,左图的和大于右图.

 

那给你一组数字,怎么构造一个赫夫曼树呢?

1.先把所有的数据节点,从小到大依次排列,成为一个有序列表

2.取出前面两个节点,让这两个节点的权重数据相加得到一个和,令这个和为根节点,这个两个节点的小的为其左孩子,大的为其右孩子

3.令这个和节点替换掉前面的两个节点,并重新排序,生成一个有序列表

4.不断重复第二步,第三步。直到所有的节点都被用完,得到一个排序结果,此时生成的二叉树,就是赫夫曼树。

 

有趣的赫夫曼树

 

赫夫曼树的实际应用:压缩数据

数据在计算机的表示形式是0,1,那么一串字符串的表示是怎么样的呢

例如ABCDEF编码如下:

有趣的赫夫曼树

那么要表示字符串“BADCADFEED”的二进制为:“001000011010000011101100100011”。

但是ABCDEF做为基本字符,在这串字符串中的出现概率是不一样的,那么我们是否可以以概率做为字符权重,对字符生成赫夫曼树呢

 

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

 

有趣的赫夫曼树

 

将权值左分支改为0,右分支改为1后的赫夫曼树。

 

根据重新编码后为:

1001010010101001000111100(共25个字符)

而原来的字符编码为:

“001000011010000011101100100011”(共30个字符)

压缩了近17%

 

解压时,按照同样的规则,还原原字符串。