WPL 和哈夫曼树

哈夫曼树,又称最优二叉树,是一棵带权值路径长度(WPL,Weighted Path Length of Tree)最短的树,权值较大的节点离根更近。

首先介绍一下什么是 WPL,其定义是树的所有叶结点的带权路径长度之和,称为树的带权路径长度,公式为 WPL = W1 * L1 + W2 * L2 + W3 * L3 + ... + Wn * Ln。

下面是个最简单且最直观的案例,通过实际案例能够更清晰的表示 WPL 和哈夫曼树。

百分制的成绩转换成五分制的成绩,伪代码如下:

if (score < 60) grade = 1;
else if (score < 70) grade = 2;
else if (score < 80) grade = 3;
else if (score < 90) grade = 4;
else grade = 5;

通过这个规则,可以生成一棵判定树,如下:

             score < 60
/ \
grade = 1 score < 70
/ \
grade = 2 score < 80
/ \
grade = 3 score < 90
/ \
grade = 4 grade = 5

根据判定树可以看出:对于 60 分以下的分数,只需要一次就能够给出结果;对于 60~70 分的成绩,需要判断 2 次给出结果;对于 70~80 的成绩则需要判断 3 次,依次类推。

那么问题来了,绝大多数成绩处于 80~90 分,只有少数成绩处于 60 分以下及 90 分以上,那判断的次数是不是有点多呢?其中这个"绝大多数"和"少数"就是一个权值的概念了。

比如成绩分布如下:

| 成绩 |  0~59  |  60~70  |  70~80  |  80~90  |  90~100  |
| 比例 | 0.05 | 0.15 | 0.30 | 0.40 | 0.10 |

那么判断次数等于: WPL = 0.05 * 1 + 0.15 * 2 + 0.30 * 3 + 0.40 * 4 + 0.10 * 5 = 3.35

这里产生一个想法:假如把 80~90 的判断拿到最前面,不就能够减少大部分成绩的计算路径了吗?

修改后的判定树应该是这样的

                                       score < 80
/ \
score < 70 score < 90
/ \ / \
score < 60 grade = 3 grade = 4 grade = 5
/ \
grade = 1 grade = 2

其判断次数等于:WPL = 0.40 * 2 + 0.30 * 2 + 0.10 * 2 + 0.15 * 3 + 0.05 * 3 = 2.2

通过上面的案例,就能够得出结论,哈夫曼树能够根据节点的查找频率来构造更有效的搜索树,是 WPL 最小的树。

哈夫曼树的构造可以理解为将权值最小的两棵二叉树合并,这个树的权值等于 2 个子树的和。

关于如何选取两个权值最小的二叉树,可以使用最小堆实现,复杂度是 O(N log N)。

比如权值:{1,2,3,4,5},可以得出:

            15   // 输出 15
/ \
6 9 // 取出 4,5 ;输出 9,得出 {6,9}
/ \ / \
3 3 4 5 // 取出 3,3 ;输出 6,得出 {6,4,5}
/ \
1 2 // 取出 1,2 ;输出 3,得出 {3,3,4,5}

计算以下 WPL = 2 * 3 + 2 * 4 + 2 * 5 + 3 * 1 + 3 * 2 = 33

哈夫曼树的特点:

    • 没有度为 1 的节点(即不存在只有一个子节点的节点)
    • n 个叶子节点的哈夫曼树,总节点数为 2n-1
      • n0:叶节点总数
      • n1:只有一个子节点的节点总数
      • n2:有两个子节点的节点总数
      • 那么 n2 = n0 - 1
      • 由于没有度为 1 的节点,所以其总节点数为 n + n - 1 = 2n-1
    • 哈夫曼树任意非叶节点的左右子树交换后仍是哈夫曼树
    • 对同一权值{W1,W2,W3,...,Wn},允许存在不同构造的两颗哈夫曼树

哈夫曼编码

哈夫曼编码用于数据存储中做压缩,如下案例:

给定一段包含 50 个字符的字符串,由 {a,b,c,d,e,f}构成,且每个字符出现次数不同,会有如下几种存储方式。

  • 等长 ASCII 编码,存储长度为 50 * 8 = 400 位
  • 等长 3 位编码,存储长度为 50 * 3 = 150 位
  • 不等长编码,出现频率高的字符编码短些,出现频率低的字符编码长些。

第三种便可以使用哈夫曼树来实现,假如给定:

| 字符 |  a  |  b  |  c  |  d  |  e  |  f  |
| 次数 | 18 | 4 | 16 | 1 | 1 | 10 |

构成哈夫曼树:

       50
0/ \1
a(18) 32
0/ \1
c(16) 16
0/ \1
6 f(10)
0/ \1
2 b(4)
0/ \1
d(1) e(1)

所以: a:0; b:1101; c:10; d:11000; e:11001; f:111 。

长度为: 1 * 18 + 4 * 4 + 16 * 2 + 1 * 5 + 1 * 5 + 10 * 3 = 106 字符。

emmm... 大概就是这么个东西。好了,笔记写完了,继续学习...

Huffman Tree (哈夫曼树学习)的更多相关文章

  1. 哈夫曼树(三)之 Java详解

    前面分别通过C和C++实现了哈夫曼树,本章给出哈夫曼树的java版本. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载请注明出处:htt ...

  2. 哈夫曼树(二)之 C++详解

    上一章介绍了哈夫曼树的基本概念,并通过C语言实现了哈夫曼树.本章是哈夫曼树的C++实现. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载 ...

  3. 哈夫曼树——c++

    哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树. 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树. 这个定 ...

  4. 哈夫曼树C++实现详解

    哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树. 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树. 这个定 ...

  5. Python---哈夫曼树---Huffman Tree

    今天要讲的是天才哈夫曼的哈夫曼编码,这是树形数据结构的一个典型应用. !!!敲黑板!!!哈夫曼树的构建以及编码方式将是我们的学习重点. 老方式,代码+解释,手把手教你Python完成哈夫曼编码的全过程 ...

  6. 哈夫曼树(Huffman Tree)与哈夫曼编码

    哈夫曼树(Huffman Tree)与哈夫曼编码(Huffman coding)

  7. 树-哈夫曼树(Huffman Tree)

    概述 哈夫曼树:树的带权路径长度达到最小. 构造规则 1. 将w1.w2.-,wn看成是有n 棵树的森林(每棵树仅有一个结点): 2. 在森林中选出根结点的权值最小的两棵树进行合并,作为一棵新树的左. ...

  8. 哈夫曼树(Huffman Tree)

    Date:2019-06-21 14:42:04 做题时更多的是用到哈夫曼树的构造思想,即按照问题规模从小到大,依次解决问题,可以得到最优解 Description: 在一个果园里,多多已经将所有的果 ...

  9. 哈夫曼树(Huffman)的JS实现

    我本身并不懂哈夫曼树也不知道有什么用,GOOGLE了下,也只是一知半解,只是刚好看到有JAVA实现版,又看了下生成原理,感觉挺有意思,就写了一下 有些地方可以优化,效率不怎么样的,纯好玩,也不保证一定 ...

随机推荐

  1. [技术博客]使用wx.downloadfile将图片下载到本地临时存储

    目录 目标 代码展示 重点讲解 目标 在上一篇技术博客中,我们生成的海报中包含图片,这些图片是存储到服务器上的,而canvas的drawimage函数只能读取本地文件,因此我们在drawCanvas之 ...

  2. Xcode一个project多个target

    project添加target https://blog.csdn.net/vbirdbest/article/details/53466009 https://www.cnblogs.com/Bob ...

  3. VS2019调试 asp.net core 2.2 出现《ANCM In-Process Handler Load Failure 发布后启动错误处理》处理

      从 google 出来的 github 上  AspNetCore issues 和 stackoverflow 搜到的,百度 博客园搜到的,CSDN 搜到的,统统设置了,不管用.   从这些问题 ...

  4. JS数据结构第一篇---算法之复杂度判断

    1.算法:算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作. 那么一个怎样的算法才能称得上是好算法,也就是说有没有什么标准来评判一个算法的好坏? 在此之 ...

  5. kali渗透

    局域网-断网&劫持(kali)   1.查看局域网中的主机 fping –asg 192.168.1.0/24 2.断网 arpspoof -i wlan0 -t 192.168.100 19 ...

  6. unity的yield

    这里说的是Unity通过StartCoroutine开启IEnumerator协程里的yield相关 1.yield return 0,yield return null 等待下一帧接着执行下面的内容 ...

  7. How to sort HashSet in Java

    How to sort HashSet in Java 方法一:By Converting HashSet to List 方法二:By Converting HashSet to TreeSet i ...

  8. Redis Desktop Manager 0.9.3 版本下载

    因为Redis Desktop Manager作者在 0.9.4 版本之后选择对所有的安装包收费,不再提供安装包下载,但是源码依旧公开.链接:https://pan.baidu.com/s/1SXsy ...

  9. TP5多字段排序

    有业务需求如下: select * from table where id IN (3,6,9,1,2,5,8,7) order by field(id,3,6,9,1,2,5,8,7); 这里直入主 ...

  10. APUE之第5章——标准I/O库

    一.知识回顾:文件I/O 文件 I/O 是不带缓冲的 I/O(unbuffered I/O),指每个 read 和 write 都调用内核中的一个系统调用. 对于内核而言,所有打开的文件都通过文件描述 ...