1 概念介绍

哈夫曼编码是一种最优的前缀编码技术,然而其存在的不足却制约了它的直接应用。首先,其解码时间为O(lavg), 其中lavg为码字的平均长度;其次,更为最重要的是,解码器需要知道哈夫曼编码树的结构,因而编码器必须为解码器保存或传输哈夫曼编码树。对于小量数据的压缩而言,这是很大的开销。因而,应用哈夫曼编码的关键是如何降低哈夫曼编码树的存储空间。Faller[1973]提出的自适应哈夫曼编码技术使哈夫曼编码树的存储空间降为零,即在使用某种约定的情况下,解码器能动态地重构出和编码器同步的哈夫曼编码树,而不需要任何附加数据。这样做的代价便是时间开销的增大。另一种技术是编码器和解码器使用事先约定的编码树,这种方法只能针对特定数据使用,不具备通用性。另外一种,也是最为常用的方法,便是范式哈夫曼编码。现在流行的很多压缩方法都使用了范式哈夫曼编码技术,如GZIB、ZLIB、PNG、JPEG、MPEG等。
范式哈夫曼编码最早由Schwartz[1964]提出,它是哈夫曼编码的一个子集。其中心思想是:使用某些强制的约定,仅通过很少的数据便能重构出哈夫曼编码树的结构。其中一种很重要的约定是数字序列属性(numerical sequence property),它要求相同长度的码字是连续整数的二进制描述。例如,假设码字长度为4的最小值为0010,那么其它长度为4的码字必为0011, 0100, 0101, ...;另一个约定:为了尽可能的利用编码空间,长度为i第一个码字f(i)能从长度为i-1的最后一个码字得出, 即: f(i) = 2(f(i-1)+1)。假定长度为4的最后一个码字为1001,那么长度为5的第一个码字便为10100。最后一个约定:码字长度最小的第一个编码从0开始。通过上述约定,解码器能根据每个码字的长度恢复出整棵哈夫曼编码树的结构。

2 码字构造

假设有如下的码长序列:
 符号:a b c d e  f  g h  i  j  k ... u
 码长:3 4 4 4 4 4 4 4 4 5 5 ... 5
使用count[i]表示长度为i的码字的数目,first[i]表示长度为i的第一个码字的整数值。根据约定3,即first[3] = 0可得到符号a的范式哈夫曼编码为000。再根据约定2,可得到first[4] = 2*(first[3]+1) = 2,进一步可知b的编码为0010。由约定1可构造出符号c的编码为0011,由此类推可构造出整个码字空间如下:
a=000(0);  f=0110(6);  k=10101(21);
b=0010(2);  g=0111(7);  ...
c=0011(3);  h=1000(8);  u=11111(31);
d=0100(4);  i=1001(9);
e=0101(5);  j=10100(20);

其中first[3] = 0, first[4] = 0010b = 2, first[5] = 10100b = 20

3 解码算法

范式哈夫曼编码有一个很重要的特性:长度为i的码字的前j位的数值大于长度为j的码字的数值,其中i > j。如上例中的最小五位码10100,它的前四位1010大于任何的四位码。由这个特性,很容易构造出范式哈夫曼编码的解码算法:
extern KBitInputStream bs;
int len = 1;
int code = bs.ReadBit();
while(code >= first[len])
{
 code <<= 1;
 code |= (bs.ReadBit()); // append next input bit to code
 len++;
}
len--;
// 至此,识别出了一个前缀码,下面将code解码为其对应的符号sym
int index = index[len]+(code-first[len]);
int sym = table[index];

其中while循环用于确定码长,这也是解码算法中至关重要的一步,确定码长的算法效率影响着整个解码算法的效率。比如说我们要解码100110100序列,当循环至len=4的时候,code等于1001,大于len[4],因而循环继续,继续读取下一位,code=10011, len=5,小于len[5]=10100,所以循环结束,执行下面的len--代码,得到了正确的码字长度4。算法实现需要注意几点:一定要使用code >= first[len],而不是code > first[len];另外,len--不能少。

代码中index[len]表示长度为len的第一个码字的索引,index[3] = 0, index[4] = 1, index[5] = 9。不难发现,index[i] = count[i-1]+count[i-2]+...+count[1]+count[0],其中count[0] = 0。

4 其他特性

对于长度为i的码字而言,count[i] <= (2^i)-first[i]。其中等号仅对最大长度的码字成立。
如果对于码字的最大长度imax,count[imax] < (2^imax)-first[imax],那么称输入的码字长度序列为不完全集。

参考文献
[1] Faller, N. 1973. An Adaptive System for Data Compression. Record of the 7th Asilomar Conf. on Circuits, Systems and Computers (Pacific Grove, Ca., Nov.), 593-597.
[2] Schwartz E.S. Kallick B,. Generating a cannonical prefix encoding, Communications of the ACM 7(1964), 166-169.

转自:http://blog.csdn.net/goncely/archive/2006/03/06/616589.aspx

转载于:https://www.cnblogs.com/k1988/archive/2010/05/18/2165645.html

范式哈夫曼编码(Canonical Huffman Code)相关推荐

  1. C#,哈夫曼编码(Huffman Code)压缩(Compress )与解压缩(Decompress)算法与源代码

    David A. Huffman 哈夫曼编码简史(Huffman code) 1951年,哈夫曼和他在MIT信息论的同学需要选择是完成学期报告还是期末考试.导师Robert M. Fano给他们的学期 ...

  2. java实现哈夫曼编码(huffman)编码

      这篇博客主要讲解如何用java实现哈夫曼编码(Huffman). 概念   首先,我来简单说一下哈夫曼编码(Huffman),它主要是数据编码的一种方式,也是数据压缩的一种方法,将某些特定的字符转 ...

  3. 哈夫曼编码(Huffman Coding)

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

  4. 哈夫曼树(Huffman Tree)及哈夫曼编码(Huffman Coding)

    目录 一.Huffman树(最优二叉树) 1.定义 2.构造 构造哈夫曼树的算法 哈夫曼树特点 二.Huffman编码 一.Huffman树(最优二叉树) 1.定义 树的带权路径长度,就是树中所有的叶 ...

  5. 2022黄文嵩商盛兰张阳徐铭信息论课程作业 哈夫曼编码(Huffman Coding)简介

    目录 5G,华为,土耳其--我花了两个月,搞懂了5G背后的秘密_哔哩哔哩_bilibili 一.什么是编码? 二.哈夫曼编码 1.编码过程 2.码方差 3.编码特点 4.人无完人,码无完码 三.总结 ...

  6. 霍夫曼编码(huffman coding) (java实现)

    文章目录 一.浅谈赫夫曼编码 二.获取赫夫曼编码 1.获取字符出现的次数 2.创建赫夫曼树 3.指定编码 三.代码实现 1.指定编码代码 2.完整代码 总结 提示:以下是本篇文章正文内容,下面案例可供 ...

  7. 霍夫曼编码(Huffman Coding)

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

  8. 使用Java实现哈夫曼编码(Huffman Coding)

    文章目录 (一)需求分析 (二)构建哈夫曼树 (三)构建哈夫曼编码 (四)哈夫曼编码的解码 (五)哈夫曼编码压缩的原理 (六)总结 (七)Java代码实现哈夫曼树:构建节点类&二叉树类 (八) ...

  9. 【知识发现】python开源哈夫曼编码库huffman

    1.哈夫曼树: 安装:pip install huffman Github地址: https://github.com/nicktimko/huffman    pypi地址:https://pypi ...

  10. 数据结构之哈夫曼编码

    例题: 假设一个文本文件TFile中只包含7个字符{A,B,C,D,E,F,G},这7个字符在文本中出现的次数为{5,24,7,17,34,5,13} 利用哈夫曼树可以为文件TFile构造出符合前缀编 ...

最新文章

  1. php-echo原理
  2. 操作系统使用户和计算机的接口 对吗,计算机操作系统教程--核心与设计原理习题10答案...
  3. 2016年5月29日周总结
  4. qq2440 cs8900移植
  5. centos 零碎学习小记 2.
  6. 让效率“爆表”的49个数据可视化工具
  7. 创建型模式之单例模式
  8. 计算机电容与晶体管等硬件的作用,太实用了|开关电源中各元器件的命名与用途!-EDA365电子论坛通信数码-人工智能-计算机-半导体-手机家电消费电子硬件门户网站...
  9. 学习基础的html代码知识(入门篇)
  10. CSDN博客模板调查问卷
  11. 人人都有发言权的新媒体时代 内容审核需亮剑
  12. 在函数中引用外部数组元素
  13. Android使用NFC读卡实现 (一)
  14. post入门篇:请求头/响应头、cookie、URL结构/编码、数据编码、winHttpRequest、post分析技巧、伪装IP
  15. 常用Pandas读取excel(或txt)部分行列并输出
  16. 公式图片转latex神器Mathpix以及latex公式与word公式的相互转换
  17. 平陆中学计算机,公示2009学科带头人骨干教师新评名单(公示)
  18. 基于贝叶斯算法的邮件过滤管理系统的设计和实现(Vue+SpringBoot)
  19. 算法(三)列举所有k-mer的组合
  20. php电子商务网站案例,基于PHP的B2C电子商务网站开发

热门文章

  1. jackson 忽略多余字段_Java进阶学习:JSON解析利器JackSon
  2. linux内核C -- 第08课:变参函数的格式检查——format
  3. Linux的软链接和硬链接
  4. Linux系统下init进程的前世今生
  5. 内部矩阵维度必须一致simulink_为何选择矩阵式KVM切换器及其原理
  6. git本地项目推动到gitlab远端服务器
  7. python中的闭包与装饰器
  8. udp聊天室的界面实现
  9. pthread 立即停止线程_iOS多线程:『pthread、NSThread』详尽总结
  10. matlab中图例的字怎么改,matlab中legend函数在添加图例时的使用方法