转载地址  :   http://blog.csdn.net/xuefeng0707/article/details/7844834

哈夫曼编码:

一种字符编码方式,常用于数据文件压缩。压缩率通常在20%~90%。

主要思想:

采取可变长编码方式,对文件中出现次数多的字符采取比较短的编码,对于出现次数少的字符采取比较长的编码,可以有效地减小总的编码长度。

例如,在英文中,e的出现频率最高,z的出现频率最低,所以可以用最短的编码来表示e,用最长的编码表示z。

例子:

一个文件包含100 000个字符,且仅含有a,b,c,d,e,f六个字符,那么可以用3位bit来编码这六个字符,称之为定长码。

那么采取定长码共需要的位数为 3* 100 000 = 600 000位。

这六个字符出现的频率如图所示,a最多,f最少。因此如果采取图中所示的变长码,所需要的位数为:

(45*1 + 13*3 + 12 * 3 + 16*3 + 9*4 + 5*4) * 1000 = 224 000。

可以看出压缩了25%,a的编码长度最短,为一位,f的编码长度最长,为4位。

前缀码:

当读取文件时,对于定长码文件,已经知道了每个字符的编码长度,所以只需按部就班的一个一个的读取字符即可;

对于变长码文件,各个字符的编码长度不一,因此需要小心设计各个字符的编码,一面混淆。

比如,如果a的编码为0,b的编码为01,c的编码为1,那么解码的时候如果遇到‘001’,则既可以解码成‘aac’,也可以解码成‘ab’。

因为b的编码中包含了a的编码,也就是a的编码是b的编码的前缀。

所以,变长码编码的设计,每个字符的编码都不能是其他字符编码的前缀,这种方式称之为前缀码

可以用二叉树来表示每个字符的编码,以左为0,以右为1,这样每个叶子节点的路径均不同,也都不会称为其他叶子节点的前缀。

这样每个叶子节点的路径,就是每个字符的编码。

图中形成的编码与表格中的有些差异,但是各个字符编码的长度都相同,这是左子树和右子树的区别,但是对编码长度没有影响。

贪心算法代码实现:

/*** Huffman code* @author xuefeng**/
public class Huffman {/*** ignore exception* @param cs : characters* @param freqs : frequency of each character*/public static void huffman(char[] cs, double[] freqs) {int n = cs.length;MinHeap<Code> heap = new MinHeap<Code>(cs.length);Code[] codes = new Code[n];for (int i = 0; i < n; i++) {Code c = new Code(cs[i], freqs[i]);heap.add(c); // 以最小堆来每次取出频率最小的两个codes[i] = c; // 保存所有的叶子节点}Code c, c1, c2;while (heap.size() > 1) {c1 = heap.removeMin();c2 = heap.removeMin();// 取出两个最小的c = new Code('\0', c1.freq + c2.freq);c.left = c1;c.right = c2;c1.parent = c;c2.parent = c;heap.add(c); // 组合成一个新的节点,并放入堆中,继续比较System.out.println(c1.val + "+" + c2.val + " : " + c1.freq + "+" + c2.freq + " = " + c.freq);}c = heap.removeMin(); // 二叉树根节点StringBuffer sb;for (int i = 0; i < n; i++) {c = codes[i]; // 从每个叶子节点,向上追溯,直到根节点,确定每个字符的编码sb = new StringBuffer();while (c != null) {if (c.parent != null) {if (c == c.parent.left) {sb.insert(0, 0); // 如果是左边的,编码取1} else {sb.insert(0, 1); // 如果是右边的,编码取1}}c = c.parent;}System.out.println(codes[i].val + " : " + sb.toString());}}public static void main(String[] args) {char[] cs = { 'a', 'b', 'c', 'd', 'e', 'f' };double[] freqs = { 45, 13, 12, 16, 9, 5 };// %huffman(cs, freqs);// http://zh.wikipedia.org/wiki/%E5%AD%97%E6%AF%8D%E9%A2%91%E7%8E%87char[] cs2 = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k','l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w','x', 'y', 'z' };double[] freqs2 = { 8.167, 1.492, 2.782, 4.253, 12.702, 2.228, 2.015,6.094, 6.966, 0.153, 0.772, 4.025, 2.406, 6.749, 7.507, 1.929,0.095, 5.987, 6.327, 9.056, 2.758, 0.978, 2.360, 0.150, 1.974,0.074 };huffman(cs2, freqs2);}
}class Code implements Comparable<Code> {public char val;public double freq;public Code left, right, parent;public Code(char val, double freq) {this.val = val;this.freq = freq;}@Overridepublic int compareTo(Code c) {double d = freq - c.freq;return d > 0 ? 1 : (d == 0 ? 0 : -1);}
}

贪心算法 - 哈夫曼编码 Huffman相关推荐

  1. 贪心算法哈夫曼编码c语言,贪心算法详解:哈夫曼编码

    理解贪心算法 贪心算法是一种算法思想,并不是一个具体的算法,因此我们用两个例子来理解什么样的问题适合用贪心算法解决. 例一 现在有一个能装 100g 物品的背包,和一些可拆分的物品(见表格),怎么装才 ...

  2. 数据结构C#版笔记--啥夫曼树(Huffman Tree)与啥夫曼编码(Huffman Encoding)

    哈夫曼树Huffman tree 又称最优完全二叉树,切入正题之前,先看几个定义 1.路径 Path 简单点讲,路径就是从一个指定节点走到另一个指定节点所经过的分支,比如下图中的红色分支(A-> ...

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

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

  4. 贪心策略——哈夫曼编码

    谈一谈贪心算法中哈夫曼编码的一些理解

  5. 算法-16-哈夫曼编码

    十六.哈夫曼编码(Huffman Coding) 1.概念 它是哈夫曼树(Huffman Tree)在电讯通信领域中的经典应用.广泛应用于数据文件的压缩,压缩率一般在20% ~ 90%之间,属于**可 ...

  6. 经典算法: 哈夫曼编码

    1.哈夫曼树的基本概念 从A结点到B结点所经过的分支序列叫做从A结点到B结点的路径:从A结点到B结点所经过的分支个数叫做从A结点到B结点的路径长度:从二叉树的根结点到二叉树中所有叶结点的路径长度之和称 ...

  7. 霍夫曼树:霍夫曼编码(Huffman Tree:Huffman Coding)

    一.简介 霍夫曼树常处理符号编写工作.根据整组数据中符号出现的频率高低,决定如何给符号编码.如果符号出现的频率越高,则给符号的码越短,相反符号的号码越长. 相关术语 路径:从书中一个节点到另一个节点之 ...

  8. python哈夫曼编码注意_Python 算法(2) 哈夫曼编码 Huffman Encoding

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

  9. 哈夫曼编码(Huffman)Java实现代码简化版

    这个网上发现的Huffuman编码Java实现在组织上相对简化,便于理解文件压缩过程:提取文件统计字符频度-根据字符频度创建huffman树-根据huffman树生成huffman可变字长无前缀编码- ...

最新文章

  1. leetcode-152 乘积最大子序列
  2. C#实现路由器断开连接,更改公网ip
  3. ajax发不出去请求_Ajax请求发送成功但不进success的解决方法
  4. 智能电源分配PDU应用
  5. Python_Mix*OS模块,序列化模块种的json,pickle
  6. 技术她力量,鹅厂女博士的寻“豹”之旅
  7. Pandas知识点-合并操作merge
  8. C语言算术运算符介绍和示例
  9. VLFeat工具包在matlab使用方法
  10. STVD、STVP、ST-LINK utility这些工具你了解吗?
  11. 机器视觉该怎么样系统学习
  12. Google Reader 推出简体中文版 Google(谷歌)阅读器
  13. java毕业设计民航售票管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  14. 最简单的51单片机软件定时器的编写
  15. 雷电模拟器忘记锁屏密码
  16. python爬虫 - 代理ip正确使用方法
  17. 《匆匆那年》的你,还记得吗?数学中的那些有(hui)趣(se)的定理(5)——鸡爪定理
  18. 手持式尘埃粒子测试仪价格,尘埃粒子一般一个点测量几次
  19. win7删除u盘linux分区,WIN7系统不用分区工具如何创建、删除和格式化分区
  20. Java中文乱码浅析及解决方案

热门文章

  1. dart系列之:在dart中使用packages
  2. Python基础之:Python中的模块
  3. 整车物流系统源代码_整车物流AGV智能搬运机器人一阶段实地测试顺利完成
  4. qt 16进制字符串和十六进制数_Python字符串类型及其操作
  5. 浅谈分布式存储系统数据分布算法
  6. 【附超时原因】1055 The World‘s Richest (25 分)_42行代码AC
  7. java tostring方法_Java程序员小伙启动项目报错,原来是使用了lombok
  8. java中的topicFont_Fontmin 快速指南
  9. Android对话框dialog大全(代码直接可用)
  10. 无盘机服务器,无盘服务器操作系统