`
realnicky
  • 浏览: 61838 次
  • 来自: 杭州
社区版块
存档分类
最新评论

哈夫曼编码简介

阅读更多

转载自http://www.thecodeway.com/blog/?p=870

哈弗曼编码几乎是所有压缩算法的基础,其实这个算法并不复杂,简单的理解就是,如何用更短的bit来编码数据
    我们知道普通的编码都是定长的,比如常用的ASCII编码,每个字符都是8个bit:

字符编码
A 00101001
B 00101010
C 00101011

    这样,计算机就能很方便的把由0和1组成的数据流解析成原始信息,但我们知道,在很多情况下,数据文件中的字符出现的概率是不均匀的,比如在一篇英语文章中,字母“E”出现的频率最高,“Z”最低,如果我们使用不定长的bit编码,频率高的字母用比较短的编码表示,频率低的字母用长的编码表示,岂不是可以大大缩小文件的空间吗?
    但这就要求编码要符合“前缀编码”的要求,即较短的编码不能是任何较长的编码的前缀,这样解析的时候才不会混淆,比如下面的编码方法就符合前缀原则:

字符编码
A 0
B 10
C 110
D 1110
E 11110

    根据这个码表,下面一段数据就可以唯一解析成原始信息了:
    1110010101110110111100010 – DABBDCEAAB

    要生成这种编码,最方便的就是用二叉树,考察一下下面这个树


    把要编码的字符放在二叉树的叶子上,所有的左节点是0,右节点是1,从根浏览到叶子上,因为字符只能出现在树叶上,任何一个字符的路径都不会是另一字符路径的前缀路径,符合前缀原则编码就可以得到

字符编码
A 00
B 010
C 011
D 10
E 11

    现在我们可以开始考虑压缩的问题,如果有一篇只包含这五个字符的文章,而这几个字符的出现的次数如下:
    A: 6次
    B : 15次
    C: 2次
    D : 9次
    E: 1次
    用过用定长的编码,每个字符3bit,这篇文章总长度为:
    3*6 + 3*15 + 3*2 + 3*9 + 3*1 = 99
    而用上面用二叉树生成的编码,总长度为:
    2*6 + 3*15 + 2*2 + 2*9 + 2*1 = 80

    显然,这颗树还可以进一步优化,使得编码更短,比如下面的编码

    生成的数据长度为:
    3*6 + 1*15 + 4*2 + 2*9 + 4*1 = 63

    可以看出,构造更优的二叉树,原则就是权重越大的叶子,距离根应该越近,而我们的终级目标是生成“最优”的二叉树,最优二叉树必须符合下面两个条件:

  1. 所有上层节点都大于等于下层节点。
  2. 某节点,设其较大的子节点为m,较小的子节点为n,m下的任一层的所有节点都应大于等于n下的该层的所有节点。

    上面这个例子是比较简单的,实际的文件中,一个字节有256种可能的取值,所以二叉树的叶子节点多达256个,最终的树形可能非常复杂,但有一种非常精巧的算法可以快速地建起一棵最优二叉树,这种算法由D.Huffman(戴?哈夫曼)提出,下面我们先来介绍哈弗曼算法的步骤,然后再来证明通过这么简单的步骤得出的树形确实是一棵最优二叉树。
    哈夫曼算法的步骤是这样的:

  • 从各个节点中找出最小的两个节点,给它们建一个父节点,值为这两个节点之和。
  • 然后从节点序列中去除这两个节点,加入它们的父节点到序列中。
  • 重复上面两个步骤,直到节点序列中只剩下唯一一个节点。这时一棵最优二叉树就已经建成了,它的根就是剩下的这个节点。

        比如上面的例子,哈弗曼树建立的过程如下:

        1) 列出原始的节点数据:

        2) 将最小的两个节点C和E结合起来:

        3) 再将新的节点和A组合起来

        4) 再将D节点加入

        5) 如此循环,最终得到一个最优二叉树

        生成的数据文件长度为:
        3*6 + 1*15 + 4*2 + 2*9 + 4*1 = 63

        下面我们用逆推法来证明对于各种不同的节点序列,用哈弗曼算法建立起来的树总是一棵最优二叉树:

    • 当这个过程中的节点序列只有两个节点时(比如前例中的15和18),肯定是一棵最优二叉树,一个编码为0,另一个编码为1,无法再进一步优化。
    • 然后往前步进,节点序列中不断地减少一个节点,增加两个节点,在步进过程中将始终保持是一棵最优二叉树,这是因为:
      1. 按照哈弗曼树的建立过程,新增的两个节点是当前节点序列中最小的两个,其他的任何两个节点的父节点都大于(或等于)这两个节点的父节点,只要前一步是最优二叉树,其他的任何两个节点的父节点就一定都处在它们的父节点的上层或同层,所以这两个节点一定处在当前二叉树的最低一层。
      2. 这两个新增的节点是最小的,所以无法和其他上层节点对换。符合我们前面说的最优二叉树的第一个条件。
      3. 只要前一步是最优二叉树,由于这两个新增的节点是最小的,即使同层有其他节点,也无法和同层其他节点重新结合,产生比它们的父节点更小的上层节点来和同层的其他节点对换。它们的父节点小于其他节点的父节点,它们又小于其他所有节点,只要前一步符合最优二叉树的第二个条件,到这一步仍将符合。

        这样一步步逆推下去,在这个过程中哈弗曼树每一步都始终保持着是一棵最优二叉树。

分享到:
评论

相关推荐

    哈夫曼编码和译码c++

    ### 哈夫曼编码简介 哈夫曼编码是一种广泛应用于数据压缩领域的算法,尤其适用于无损数据压缩。该算法是由David A. Huffman在1952年提出的。其基本思想是构建一棵哈夫曼树,并根据这棵树来为每种字符或符号分配一个...

    哈夫曼编码实验报告 数据结构

    一、哈夫曼编码简介 哈夫曼编码是1952年由David A. Huffman提出的一种变长编码方式,其核心思想是根据字符出现的频率来分配编码,频率越高的字符,编码长度越短,反之则越长。这样可以最大限度地减少数据的存储空间...

    哈夫曼编码实验报告

    #### 一、哈夫曼编码简介与原理 哈夫曼编码是一种广泛应用于数据压缩领域的编码技术,由David A. Huffman于1952年提出。该编码方法是基于字符出现频率而构建的一种变长前缀编码,能够有效地提高信道利用率,缩短...

    哈夫曼编码C语言实现-利用哈夫曼编码进行通信可以大大提高信道的利用率

    利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。 从键盘输入若干字符及每个字符出现的频率,...

    哈夫曼编码,以及通过老师的验证

    #### 一、哈夫曼编码简介 哈夫曼编码(Huffman Coding)是一种广泛应用于数据压缩领域的编码方式,由David A. Huffman于1952年提出。其核心思想是为数据中的每个字符分配一个长度可变的前缀码(即没有字符的编码是...

    哈夫曼编码计算信源熵及编码效率

    哈夫曼编码计算信源熵及编码效率 哈夫曼编码是一种变长前缀编码方法,它可以根据信源符号的概率分布计算信源熵和编码效率。本文将详细介绍哈夫曼编码的原理、步骤和实现方法。 哈夫曼编码的原理 哈夫曼编码的原理...

    哈夫曼树与哈夫曼编码

    哈夫曼树与哈夫曼编码是数据结构和算法领域中的一个重要概念,广泛应用于数据压缩、文本编码以及优先队列等场景。哈夫曼编码是一种特殊的前缀编码方法,能够为字符提供一种高效的二进制表示,使得频繁出现的字符具有...

    哈夫曼编码的贪心算法设计

    ### 哈夫曼编码的贪心算法设计 #### 实验背景与意义 哈夫曼编码是一种广泛应用的数据压缩技术,特别是在文件压缩领域有着极其重要的作用。哈夫曼编码利用了贪心算法的思想来构建最优的前缀编码树,进而达到高效...

    简单哈夫曼编码实例

    哈夫曼编码是一种高效的数据编码方法,主要用于无损数据压缩。它的原理是为每个字符分配一个唯一的二进制编码,使得频繁出现的字符拥有较短的编码,而不常出现的字符则有较长的编码,以此来减少平均编码长度,达到...

    三元哈夫曼编码 哈夫曼树

    在计算机科学中,哈夫曼编码是一种广泛应用于数据压缩的编码方法,其核心在于利用变长编码的方式,对字符出现频率进行有效编码,从而减少数据的存储空间和传输时间。哈夫曼编码的背后支撑是哈夫曼树,这种特殊的...

    图像处理哈夫曼编码程序

    哈夫曼编码是一种高效的数据编码方法,主要用于无损数据压缩,尤其在文本和图像处理领域广泛应用。它基于字符出现频率构建最优的二叉树结构,使得频繁出现的字符占用更短的编码,从而提高压缩效率。这个“图像处理...

    Java实现哈夫曼编码

    #### 哈夫曼编码简介 哈夫曼编码(Huffman Coding)是一种广泛应用于数据压缩领域的编码技术,它是由David Huffman在1952年提出的。这种编码方式的核心思想是根据数据出现的频率,为每个字符分配一个变长的二进制码...

    哈夫曼编码 源程序 附详细注释

    #### 一、哈夫曼编码简介 哈夫曼编码是一种广泛应用于数据压缩领域的编码算法,由David A. Huffman于1952年提出。其核心思想是通过构建一棵哈夫曼树来实现对数据的有效编码,使得出现频率高的字符具有较短的编码,...

    c语言实现哈夫曼编码

    哈夫曼编码是一种高效的数据压缩方法,由大卫·艾伦·哈夫曼在1952年提出。它是基于字符频率构建的一种前缀编码,能够为频繁出现的字符分配较短的编码,从而减少数据存储空间,提高传输效率。在C语言中实现哈夫曼...

    哈夫曼编码matlab程序

    ### 哈夫曼编码MATLAB程序解析 #### 前言 哈夫曼编码是一种广泛应用在数据压缩领域的编码方式,其核心思想是通过构建一棵特殊的二叉树(哈夫曼树)来实现对不同字符的高效编码。该编码方法在确保原始数据可被完全...

    哈夫曼编码C语言程序

    哈夫曼编码是一种高效的数据压缩方法,主要用于无损数据压缩,尤其在文本文件的压缩中效果显著。它基于字符出现频率构建最小带权路径长度(Minimum Weighted Path Length, MWPL)的二叉树,也被称为哈夫曼树。在这个...

    哈夫曼编码算法实现

    哈夫曼编码算法实现 哈夫曼编码是一种变长编码技术,用于压缩数据,提高信道的利用率,缩短信息传输的时间,降低传输成本。哈夫曼编码的原理是根据字符出现的频率,建立哈夫曼树,然后对各个字符进行哈夫曼编码。 ...

    哈夫曼编码译码器

    哈夫曼编码是一种高效的数据压缩方法,源自于数据结构中的二叉树理论,由David A. Huffman在1952年提出。它基于频率最小的编码原则,通过构建一棵特殊的二叉树(哈夫曼树)来为每个字符或符号生成唯一的前缀编码,...

    哈夫曼编码C++实现

    哈夫曼编码是广泛用于数据文件压缩的十分有效的编码方式,其压缩率通常在20%—90%之间。哈夫曼编码算法是通过使用字符在文件中出现的频率表来构造最优前缀码的贪心算法。所谓前缀码,即是任一字符的编码都不是其他...

Global site tag (gtag.js) - Google Analytics