Huffman编码(Huffman树)

【0】README

0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解 “Huffman编码(Huffman树)” 的idea 并用源代码加以实现;
0.2) Huffman树的构建算法属于 贪婪算法, 贪婪算法的基础知识参见:  http://blog.csdn.net/pacosonswjtu/article/details/50071159


【1】Huffman 编码

1.1)贪婪算法的第二个应用: 文件压缩;

  • 1.1.1)标准的 ASCII字符集: 它由大约100个 可打印字符组成,为了把这些字符区分开, 需要 |log100|(不小于等于log100) = 7个 比特;
  • 1.1.2)看个荔枝:(使用一个标准编码方案)
    设一个文件, 它只包含字符 a, e, i, s, t, 加上一些空格和 newline(换行)。 进一步设该文件有10个a、15个e、12个i、3个s、4个t、13个空格以及一个 newline, 如图10-8所示, 这个文件需要174个bits 来表示,因为有58个字符,每个字符3个bits;
    这里写图片描述
    1.2)现实中的事实: 文件可能相当大。 许多大文件是某个程序的输出数据,而在使用频率最大和最小之间的字符间通常存在很大的差别;

  • 1.2.1)出现的问题:是否有可能提供一种更好的编码降低总的所需bits数量

2.2)解决方法:一般策略就是让代码的长度从字符到字符是编号不等的, 同时保证经常出现的字符其代码短;(注意, 如果所有的字符都以相同的频率出现, 那么要节省空间是不可能的)
2.3)代表字母的二进制代码用二叉树来表示:
这里写图片描述
对上图的分析(Analysis):

  • A1)上图中的树只在树叶上有数据。 每个字符通过从根节点开始用0指示 左分支用1指示右分支 而以记录路径的方法表示出来。如, s通过从根向左走, 然后向右, 最后再向右而达到, 于是它被编码为 011。这种数据结构叫做 trie树;(trie==单词查找树)
  • A2)如果字符 ci 在深度 di 处并且出现 fi次, 那么该字符编码的值就等于 ∑di * fi;
  • A3)因为 newline(nl)是仅有的一个儿子,我们把它放到它的更高一层的父节点上, 如下图所示:
    这里写图片描述
  • A4)上图中的树是满树(full tree):所有的节点或者是树叶,或者有两个儿子;

1.4)综上所述: 我们看到,基本的问题在于找到总价值最小的满二叉树,其中所有的字符都位于树叶上, 下图显示了简单字母表的最优树:
这里写图片描述

  • 1.4.1)那么问题来了:如何构造编码树;
  • 1.4.2)解决方法(引入哈夫曼编码): 1952年 Huffman 给出了一个算法, 因此,这种编码系统通常称为 哈夫曼编码(Huffman code);

【2】哈夫曼算法

2.1)算法描述:
算法对一个由树组成的森林 进行。一棵树的权等于它的树叶的频率的和。任意选取最小权的两颗树T1 和 T2, 并任意形成以 T1 和 T2 为子树的新树, 将这样的过程进行 C-1 次。在算法的开始, 存在C 颗单节点树——每个字符一颗。在算法结束时得到一颗树, 这颗树就是最优哈夫曼编码树了;
2.2)看个荔枝(构建哈夫曼编码树的steps):

2.3)下面,我们验证哈夫曼算法产生最优代码的证明思路:

  • step1)首先 ,由反证法证明树是满的, 因为我们已经看到一颗不满的树是改进进成满树的;
  • step2)其次,我们必须证明两个频率最小的字符 α和β必然是两个最深的节点;
  • step3)然后,我们再证明, 在相同深度上任意两个节点处的字符可以交换而不影响最优性;这说明, 总可以找到一颗树, 它含有两个最不经常出现的符号作为兄弟;

2.4)该算法是贪婪算法的原因在于: 在每一阶段我们都进行一次合并而没有进行全局的考虑, 我们只是选择两颗最小的树;
2.5) 如何实现?

  • method1)如果我们依权排序将这些树保存在一个优先队列中, 那么, 由于对元素个数不超过C的优先队列将进行一次 buildHeap , 2C -2 次 deleteMin 和 C-2 次insert, 故运行时间为 O(ClogC)。
  • method2)使用一个链表简单实现该队列将给出一个O(C^2)算法;
  • Conclusion) 优先队列实现方法的选择取决于C有多大: 在ASCII 字符集下,C是足够小的, 这使得二次运行时间是可以接收的。 在这样的应用中, 实际上几乎所有的运行时间都将花费在读入输入文件和写出压缩文件所需要的磁盘I/O 操作上;

2.6)有两个细节要考虑(details)

  • d1)第一个问题是: 首先, 在压缩文件的开头必须传送编码信息,因为否则将不可能译码;对于一些小文件,传送编码信息表的代价将超过压缩带来的任何可能的节省, 最后的结果很可能是文件扩大。 当然,这可以检测到且原文件可以原样保留; 而对于大型文件, 信息表的大小是无关紧要的;
  • d2)第二个问题是: 该算法是一个两趟扫描算法。 第一遍搜集频率数据, 第二遍进行编码。显然, 对于处理大型文件的程序来说,这个性质不是我们所需要的;

【3】source code + printing results

3.1)download source code: https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter10/p266_huffman
3.2)source code at a glance:(for complete code , please click the given link above)

1st func: building huffman tree

// building huffman tree 
void buildHuffman()
{    ElementTypePtr temp;        char* codes;int off;off = 0;codes = buildCharArray(off+1);temp = buildElement();  initElement(temp);while(!isEmpty(bh)){   insertHeap(*temp, bh);      initElement(temp);}   temp->code = '\0';printf("\n=== the huffman tree we built just now is follows: ===\n");printHuffmanTree(temp, 1);printf("\n=== the huffman codes of left subtree ===\n");printHuffmanCode(temp->left, 1, off, codes);printf("\n=== the huffman codes of right subtree ===\n");printHuffmanCode(temp->right, 1, off, codes);
}

2nd func: print huffman tree node


void copyCharArray(char *a, char *b, int size)
{int i;for(i=0; i<=size; i++)a[i] = b[i];
}void printHuffmanTree(ElementTypePtr root, int depth)
{        int i;if(root) {               for(i = 0; i < depth; i++)printf("    ");             if(root->left!=NULL)        printf("%d\n", root->key);      elseprintf("%d->%c\n", root->key, root->flag);printHuffmanTree(root->left,depth+1); printHuffmanTree(root->right, depth+1); // Attention: there's difference between traversing binary tree and common tree                          }else {for(i = 0; i < depth; i++)printf("    ");     printf("NULL\n");}
}

3rd func: print huffman code of every node

void printHuffmanCode(ElementTypePtr root, int depth, int off, char *codes)
{   int i;  char *innerCode = buildCharArray(off+2); copyCharArray(innerCode, codes, off);if(root) {   innerCode[off] = root->code;innerCode[++off] = '\0';            for(i = 0; i < depth; i++)printf("    ");     if(root->left!=NULL)        printf("%d\n", root->key);      elseprintf("%d->%c->%s\n", root->key, root->flag, innerCode);printHuffmanCode(root->left,depth+1, off, innerCode); printHuffmanCode(root->right, depth+1, off, innerCode); // Attention: there's difference between traversing binary tree and common tree                          }else {for(i = 0; i < depth; i++)printf("    ");     printf("NULL\n");}
}

3.3)printing results:
这里写图片描述
这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331842.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java获取文件列表_java获取指定目录中的文件列表

最近项目中会动态生成文件html及相关资源文件(css,js,png,mp3)&#xff0c;为了防止文件名重复&#xff0c;需要获取目录中相同类型文件的最大编号&#xff0c;下面我用代码来实现获得文件列表。public static void getFiles(String path) {File file new File(path);// 如果这…

jep290涉及jdk版本_针对JDK 14提议的另外六个JEP

jep290涉及jdk版本Mark Reinhold最近的消息宣布了六个新的“建议针对JDK 14的JEP ”&#xff1a; JEP 345 &#xff0c; JEP 361 &#xff0c; JEP 363 &#xff0c; JEP 364 &#xff0c; JEP 365和JEP 367 。 假设没有异议由11月7日提出&#xff0c;这些JEPs将有针对性地JDK …

近似装箱问题(三种联机算法实现)

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在 理解 “近似装箱问题&#xff08;三种联机算法实现&#xff09;” 的idea 并用源代码加以实现&#xff1b; 0.2&#xff09; 近似装箱问题的三种联机算法 分别是&am…

java 随机数种子_Java--随机数和随机数种子(转)

在计算机中并没有一个真正的随机数发生器&#xff0c;但是可以做到使产生的数字重复率很低&#xff0c;这样看起来好象是真正的随机数&#xff0c;实现这一功能的程序叫伪随机数发生器。有关如何产生随机数的理论有许多&#xff0c;如果要详细地讨论&#xff0c;需要厚厚的一本…

java 堆转储快照_捕获Java堆转储的7个选项

java 堆转储快照堆转储是诊断与内存相关的问题的重要工件&#xff0c;例如内存泄漏缓慢&#xff0c;垃圾回收问题和java.lang.OutOfMemoryError。它们也是优化内存消耗的重要工件。 有很棒的工具&#xff0c;例如Eclipse MAT和Heap Hero&#xff0c;可以分析堆转储。 但是&…

java 提取url参数_Java提取URL某个参数的值

ASP&period;NET Core 中文文档 第四章 MVC(4&period;3)过滤器原文:Filters 作者:Steve Smith 翻译:刘怡(AlexLEWIS) 校对:何镇汐 ASP.NET MVC 过滤器 可在执行管道的前后特定阶段执行代码.过滤器可以配置为全局有效.仅对控 ...jquery插件-表单提交插件-jQuery&peri…

近似装箱问题(两种脱机算法实现)

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在 理解 “近似装箱问题&#xff08;两种脱机算法实现&#xff09;” 的idea 并用源代码加以实现&#xff1b; 0.2&#xff09; 近似装箱问题的两种联机算法 分别是&am…

vaadin 10+_Vaadin 10+作为CUBA UI的未来

vaadin 10从一开始&#xff0c;Vaadin就成为CUBA平台用户界面的基石和重要组成部分。 凭借其创新的方法&#xff0c;它帮助CUBA将企业用户界面开发带到了一个非常有希望&#xff08;当今是默认&#xff09;的WEB领域。 Vaadin最令人兴奋的部分之一是整个开发都是同构的&#xf…

java 信息增益_对信息增益(IG,Information Gain)的理解和计算

可能理解的不对。决策树构建中节点的选择靠的就是信息增益了。信息增益是一种有效的特征选择方法&#xff0c;理解起来很简单&#xff1a;增益嘛&#xff0c;肯定是有无这个特征对分类问题的影响的大小&#xff0c;这个特征存在的话&#xff0c;会对分类系统带来多少信息量&…

使用文本编辑器和jdk_JDK 14:记录,文本块等

使用文本编辑器和jdk今天的Mark Reinhold帖子“ 建议JEP针对JDK 14&#xff1a;305、343、359、366和368 ”建议将另外五个JEP针对JDK 14 。 该组中有一些备受期待的功能&#xff0c;但建议将所有功能都“预览”或“孵化”&#xff1a; JEP 305 &#xff1a;instanceof的模式匹…

java compareable接口_Java对象比较-Comparable和Comparator接口使用

最近在学习贪心算法和动态规划的过程中&#xff0c;里面有一段自然排序的操作&#xff0c;顺便简单了解一下Java中对象比较后排序要使用的两个接口&#xff1a;Comparable和Comparator。如果是数字&#xff0c;直接比较就行&#xff0c;但是如果是对象&#xff0c;如何比较后排…

java初学者指南_Java代理初学者指南

java初学者指南尽管Java初学者很快学会了键入public static void main来运行他们的应用程序&#xff0c;但是即使是经验丰富的开发人员也常常不知道JVM对Java流程的两个附加入口点的支持&#xff1a; premain和agentmain方法。 这两种方法都允许所谓的Java代理在驻留在其自己的…

java txt html格式_java中xml(txt/html等格式)解析问题,请教java高手,请勿粘贴其他网页上的内容(能查的都看了)。...

目的&#xff1a;通过对网页内容解析&#xff0c;获得需要的内容&#xff0c;如网页的标题Title&#xff0c;主要内容&#xff0c;描述信息&#xff1b;而里面的广告、超链接、无关紧要的信息统统不要&#xff0c;从而达到对用户上网行为的分析的目的。下面是我...目的&#xf…

java泛型程序设计——定义简单泛型类+泛型方法

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 定义泛型类泛型方法的知识&#xff1b; 【1】一个泛型类&#xff1a; 就是具有一个或多个类型变量的类&#xff1b; 1.1&#xff09;看个荔枝&#xff1a; …

分布式 虚拟时间和虚拟同步_分布式虚拟跟踪

分布式 虚拟时间和虚拟同步跟踪提供了对系统的可见性&#xff0c;使开发人员和操作人员可以在运行时观察应用程序。 当系统不断增长并与更多微服务进行交互时&#xff0c;跟踪变得非常有价值。 在这样的环境中&#xff0c;这些痕迹非常棒&#xff0c;可以定位导致性能下降的故障…

java泛型程序设计——类型变量限定 + 泛型代码和虚拟机

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 类型变量限定 泛型代码和虚拟机 的知识&#xff1b; 【1】类型变量的限定 1.1&#xff09;类和方法需要对类型变量加以限定 1.1.1&#xff09;看个荔枝&a…

java中装饰器_Java设计模式12:装饰器模式

装饰器模式装饰器模式又称为包装(Wrapper)模式。装饰器模式以多客户端透明的方式扩展对象的功能&#xff0c;是继承关系的一个替代方案。装饰器模式的结构通常给对象添加功能&#xff0c;要么直接修改对象添加相应的功能&#xff0c;要么派生子类来扩展&#xff0c;抑或是使用对…

selenium 4_Selenium4 Alpha –期望什么?

selenium 4Selenium4 Alpha-期望什么&#xff1f; 早在2018年8月&#xff0c;整个测试自动化社区就受到了一个重大新闻的打击&#xff1a;Selenium的创始成员Simon Stewart在班加罗尔Selenium会议上正式确认了Selenium 4的发布日期和一些重大更新。 世界最受欢迎的Web测试自动化…

英文论文中“such as, for example, e.g., i.e., etc., et al. ”的用法分析

【1】README 本文转自&#xff1a; http://www.cnblogs.com/lanke_2009/archive/2010/12/07/1899185.html &#xff0c; 旨在学习 英文论文中的 如 “such as, for example, e.g., i.e., etc., et al. ”的用法&#xff1b; 【2】正文如下&#xff1a; 黄龙旺  龚汉忠 (上…

mysql8.0云时代_8.0.22Mysql的详细安装

Mysql8.0.22的安装和常见问题前言提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考一、MySQL的下载和安装&#xff1f;1.mysql官网下载&#xff1a;https://dev.mysql.com/downloads/mysql/2.下载步骤&#xff1a;可以点击Go to download page 去下载32位的…