转载自:click here

1.哈夫曼编码的起源:

哈夫曼编码是 1952 年由 David A. Huffman 提出的一种无损数据压缩的编码算法。哈夫曼编码先统计出每种字母在字符串里出现的频率,根据频率建立一棵路径带权的二叉树,也就是哈夫曼树,树上每个结点存储字母出现的频率,根结点到结点的路径即是字母的编码,频率高的字母使用较短的编码,频率低的字母使用较长的编码,使得编码后的字符串占用空间最小。

2.哈夫曼树构造的过程:

首先统计每个字母在字符串里出现的频率,我们把每个字母看成一个结点,结点的权值即是字母出现的频率,我们把每个结点看成一棵只有根结点的二叉树,一开始把所有二叉树都放在一个集合里。接下来开始如下编码:

步骤一:从集合里取出两个根结点权值最小的树 a 和 b,构造出一棵新的二叉树 c,二叉树 c 的根结点的权值为 a 和 b 的根结点权值和,二叉树 c 的左右子树分别是 a 和 b。

步骤二:将二叉树 a 和 b 从集合里删除,把二叉树 c 加入集合里。

重复以上两个步骤,直到集合里只剩下一棵二叉树,最后剩下的就是哈夫曼树了。

我们规定每个有孩子结点的结点,到左孩子结点的路径为 0,到右孩子结点的路径为 1。每个字母的编码就是根结点到字母对应结点的路径。

3.实例模拟哈夫曼树的构造:

例如有这一个字符串“good good study day day up”,现在我们要对字符串进行哈夫曼编码,该字符串一共有 26 个字符,10 种字符,我们首先统计出每个字符的频率,然后按从大到小顺序排列如下(第二列的字符是空格):

我们把每个字符看成一个结点,权值是字符的频率,每个字符开始都是一棵只有根结点的二叉树,如下图。

1.从集合里取出根结点权值最小的两棵树 I 和 J 组成新的二叉树 IJ,根结点权值为 1 + 1 = 2,将二叉树 IJ 加入集合,把 I 和 J 从集合里删除,如下图。

2.从集合里取出根结点权值最小的两棵树 H 和 G 组成新的二叉树 HG,根结点权值为 1 + 2 = 3,将二叉树 HG 加入集合,把 H 和 G 从集合里删除,如下图。

3.从集合里取出根结点权值最小的两棵树 E 和 F 组成新的二叉树 EF,根结点权值为 2 + 2 = 4,将二叉树 EF 加入集合,把 E 和 F 从集合里删除,如下图。

4.从集合里取出根结点权值最小的两棵树 IJ 和 D 组成新的二叉树 IJD,根结点权值为 2 + 3 = 5,将二叉树 IJD 加入集合,把 IJ 和 D 从集合里删除,如下图。

5.从集合里取出根结点权值最小的两棵树 GH 和 C 组成新的二叉树 GHC,根结点权值为 3 + 4 = 7,将二叉树 GHC 加入集合,把 GH 和 C 从集合里删除,如下图。

6.从集合里取出根结点权值最小的两棵树 EF 和 B 组成新的二叉树 EFB,根结点权值为 4 + 5 = 9,将二叉树 EFB 加入集合,把 EF 和 B 从集合里删除,如下图。

7.从集合里取出根结点权值最小的两棵树 IJD 和 A 组成新的二叉树 IJDA,根结点权值为 5 + 5 = 10,将二叉树 IJDA 加入集合,把 IJD 和 A 从集合里删除,如下图。

8.从集合里取出根结点权值最小的两棵树 EFB 和 GHC 组成新的二叉树 EFBGHC,根结点权值为 9 + 7 = 16,将二叉树 EFBGHC 加入集合,把 EFB 和 GHC 从集合里删除,如下图。

9.从集合里取出根结点权值最小的两棵树 EFBGHC 和 IJDA 组成新的二叉树 EFBGHCIJDA,根结点权值为 16 + 10 = 26,将二叉树 EFBGHCIJDA 加入集合,把 EFBGHC 和 IJDA 从集合里删除,如下图。

到这里我们发现集合里就剩一棵二叉树了,那么编码结束,最后这棵二叉树就是我们要得到的哈夫曼树。接下来我们规定非叶子结点的结点,到左子树的路径记为 0,到右子树的路径记为 1,如下图:

根结点到每个叶子结点的路径便是其对应字母的编码了,于是我们可以得到:

下面我们来算一下哈夫曼树的带权路径长度 WPL,也就是每个叶子到根的距离乘以叶子权值结果之和。

WPL = 5 * 2 + 5 * 3 + 4 * 3 + 3 * 3 + 2 * 4 + 2 * 4 + 2 * 4 + 1 * 4 + 1 * 4 + 1 * 4 = 82。

我们来算下如果直接存储字符串需要多少个比特,我们知道一个字符占一个字节,一个字节占 8 个比特,所以一共需要 8 * 26 = 208 个比特。我们再来看看哈夫曼编码需要多少个比特,我们可以发现 WPL 也就是编码后原来字符串所占的比特总长度 82。显然,哈夫曼编码把原数据压缩了好多,而且没有损失。

根据上面的实例分析,我们得出哈夫曼编码的一些性质:

1.在哈夫曼树上,相对来说,权值大的结点离根结点近,权值小的结点离根结点远

2.哈夫曼编码每次从集合里取出根结点权值最小的两棵二叉数构成新的二叉树

3.哈夫曼树的 WPL(树的带权路径长度),等于编码后字符串所占的比特数

4.哈夫曼树上不会存在只有一个孩子结点的结点

(转载)哈夫曼编码(Huffman)的更多相关文章

  1. 数据压缩之经典——哈夫曼编码(Huffman)

    (笔记图片截图自课程Image and video processing: From Mars to Hollywood with a stop at the hospital的教学视频,使用时请注意 ...

  2. 赫夫曼\哈夫曼\霍夫曼编码 (Huffman Tree)

    哈夫曼树 给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离 ...

  3. 哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)

    前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Metho ...

  4. 采用霍夫曼编码(Huffman)画出字符串各字符编码的过程并求出各字符编码 --多媒体技术与应用

    题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...

  5. 霍夫曼编码(Huffman)

    题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...

  6. Python 算法(2) 哈夫曼编码 Huffman Encoding

    这个问题原始是用来实现一个可变长度的编码问题,但可以总结成这样一个问题,假设我们有很多的叶子节点,每个节点都有一个权值w(可以是任何有意义的数值,比如它出现的概率),我们要用这些叶子节点构造一棵树,那 ...

  7. 霍夫曼编码(Huffman Coding)

    霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...

  8. 哈夫曼编码的理解(Huffman Coding)

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最 ...

  9. HDU2527 哈夫曼编码

    Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  10. hdu2527哈夫曼编码

    /* Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...

随机推荐

  1. ios新手开发——toast提示和旋转图片加载框

    不知不觉自学ios已经四个月了,从OC语法到app开发,过程虽然枯燥无味,但是结果还是挺有成就感的,在此分享我的ios开发之路中的小小心得~废话不多说,先上我们今天要实现的效果图: 有过一点做APP经 ...

  2. querySelector系列方法相比 getElementsBy 系列方法有什么区别?

    querySelector 和  querySelectorAll 相比下面这些方法有什么区别? getElementsByTagName getElementsByClassName getElem ...

  3. css知识点整理

    CSS是Cascading Style Sheets的简称,中文称为层叠样式表,用来控制网页数据的表现,可以使网页的表现与数据内容分离. 一.css引入的方式 1.行内样式:行内式是在标记的style ...

  4. ReactNative中iOS和Android的style分开设置教程

    reactnative可以编辑iOS程序也可以编辑Android程序, 而且80%的代码都可以重用. 及有些文件是两个系统通用的, 相信大家也都清楚了. 但是也许大家会遇到一些屏幕布局的问题, 最常遇 ...

  5. Android 5.X新特性之RecyclerView基本解析及无限复用

    说到RecyclerView,相信大家都不陌生,它是我们经典级ListView的升级版,升级后的RecyclerView展现了极大的灵活性.同时内部直接封装了ViewHolder,不用我们自己定义Vi ...

  6. javaScript基础语法(上)

    相关理论概念: 直接量的概念:直接描述某个(些)存储空间的值的量,如变量的值.对象的值.数组的值. 数据类型:在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作. 1.变量的声明和使用 变 ...

  7. ASP.NET MVC 3 网站优化总结(一) 使用 Gzip 压缩

    网站开启 Gzip 压缩的好处相信很多人都已经清楚,这样做可以提高网站的性能.那么为什么很多网站没有开启 Gzip 压缩功能呢?原因有4点:防病毒软件.浏览器 bug.网站代理和服务器未配置. 使用 ...

  8. 11、项目经理要阅读的书籍 - IT软件人员书籍系列文章

    项目经理是负责软件项目的总体把控的角色.项目经理在项目中是一个管理者的角色,他需要对项目的9大领域进行学习,同时针对项目的范围.进度.沟通和风险进行处理,让项目能够按时保质保量的完成. 项目经理需要学 ...

  9. 梳理delegate相关概念

    一.前言 可能项目规模较小,项目中除了增删改查就只剩下业务流程,以前都没怎么弄明白的东西时间长了就越发的模糊了... 二.使用场景 MSDN:delegate 是一种可用于封装命名或匿名方法的引用类型 ...

  10. oracel数据导出导入

    一.导出模式(三种模式)及命令格式 1. 全库模式 exp 用户名/密码@网络服务名 full=y file=路径\文件名.dmp log=路径\文件名.log 2. 用户模式(一般情况下采用此模式) ...