【问题标题】:Maximum number of different numbers, Huffman Compression不同数字的最大数量,霍夫曼压缩
【发布时间】:2012-01-16 20:12:06
【问题描述】:

我想使用霍夫曼压缩来压缩许多 32 位数字。

每个数字可能出现多次,我知道每个数字都会被一些位序列替换:

111 010 110 1010 1000 等等……

现在的问题是:在二进制序列的长度超过 32 位之前,可以将多少个不同的数字添加到霍夫曼树?

生成序列的规则(对于那些不知道的人)是,每次添加一个新数字时,您必须为其分配可能不是另一个前缀的最小二进制序列。

【问题讨论】:

  • 理论上,最多可以将 2^32 个序列添加到高度为 32 的树中。在这种情况下,它将表示以相同频率出现的所有可能的 32 位数字。并且为每个数字生成的霍夫曼代码将是 32 位。
  • 是的,我已经阅读了霍夫曼的基础知识,我也实现了它。

标签: huffman-code


【解决方案1】:

你好像明白前缀码的原理了。

许多人(令人困惑)将所有前缀代码称为“霍夫曼代码”。

还有许多其他类型的前缀码——它们将数据压缩成比霍夫曼压缩更少的位数(如果我们忽略传输频率表的开销),但它们中的许多都非常接近(某些类型的数据)并具有其他优势,例如运行速度更快或保证某些最大代码长度(“长度限制前缀代码”)。

如果您有大量唯一符号,则霍夫曼频率表的开销会变得很大——也许其他一些前缀代码可以提供更好的网络压缩。

许多在硬件中进行压缩和解压缩的人对最大码字大小有固定的限制——许多图像和视频压缩算法都指定了“长度受限的霍夫曼码”。

最快的前缀码——universal codes——事实上,包含一系列可以预先生成的位序列,而无需考虑实际符号频率。正如您所提到的,使用这些代码的压缩程序会将最频繁的输入符号与最短的位序列相关联,将次频输入符号与下一个缩短的位序列相关联,依此类推。

例如,一些压缩程序使用Fibonacci codes(一种通用代码),并且总是将最频繁的符号关联到位序列“11”,将次频符号关联到位序列“011” "、"0011" 的旁边、"1011" 的旁边等等。

霍夫曼算法生成的代码在许多方面与通用代码相似——两者都是前缀代码。 但是,正如 Cyan 指出的那样,霍夫曼算法与那些通用代码略有不同。 如果您有 5 个不同的符号,则 Huffman 树将包含 5 个不同的位序列 - 但是,the Huffman algorithm 生成的确切位序列取决于确切的频率。 一个文档的符号计数可能为 { 10, 10, 20, 40, 80 },导致 Huffman 位序列 {0000 0001 001 01 1 }。 另一个文档可能有 {40, 40, 79, 79, 80} 的符号计数,导致霍夫曼比特序列 {000 001 01 10 11}。 尽管这两种情况都恰好有 5 个唯一符号,但在这两个压缩文档中,最常见符号的实际 Huffman 代码非常不同——一个文档中的 Huffman 代码“1”,另一个文档中的 Huffman 代码“11”。 但是,如果您使用 Fibonacci 代码压缩这些文档,则最常见交易品种的 Fibonacci 代码始终相同——每个文档中的“11”。

特别是对于斐波那契,第一个 33 位斐波那契码是“31 个零位,后跟 2 个 1 位”,表示值 F(33) = 3,524,578 。 因此 3,524,577 个唯一符号可以用 32 位或更少的斐波那契码表示。

前缀码的一个更违反直觉的特征是某些符号(稀有符号)被“压缩”成更长的位序列。 如果您实际上有 2^32 个唯一符号(所有可能的 32 位数字),则如果您强制压缩器使用限制为 32 位或更少的前缀代码,则无法获得任何压缩。 如果您实际上有 2^8 个唯一符号(所有可能的 8 位数字),则如果您强制压缩器使用限制为 8 位或更少的前缀代码,则不可能获得任何压缩。 通过允许压缩器扩展稀有值——使用超过 8 位来存储我们知道可以以 8 位存储的稀有符号——或者使用超过 32 位来存储稀有符号我们知道 可以 存储在 32 位中——这让压缩器可以使用少于 8 位——或少于 32 位——来存储更频繁的符号。

特别是,如果我使用斐波那契代码来压缩值表, 其中值包括所有可能的 32 位数字, 必须使用长达 N 位的斐波那契代码,其中 F(N) = 2^32 - 求解 N 我得到 对于最不常用的 32 位符号,N = 47 位。

【讨论】:

    【解决方案2】:

    哈夫曼是关于压缩的,而压缩需要一个“倾斜”的分布才能工作(假设我们谈论的是正态、0 阶、熵)。

    关于霍夫曼树深度的最坏情况是算法创建退化树时,即每个级别只有一个叶子。如果分布看起来像斐波那契数列,则可能会发生这种情况。

    因此,最差的分布顺序如下所示:1、1、1、2、3、5、8、13、...

    在这种情况下,您只需用 33 个不同的元素填充完整的 32 位树。

    但是请注意,要达到 32 位深度,只有 33 个元素,最多的元素必须出现 3 524 578 次。

    因此,由于将所有斐波那契数相加得到 5 702 886,因此您需要压缩至少 5 702 887 个数,以开始面临无法用 32 位霍夫曼树表示它们的风险。

    话虽如此,使用 Huffman 树表示 32 位数字需要大量内存来计算和维护树。

    [编辑] 一种更简单的格式,称为“对数近似”,对所有符号赋予几乎相同的权重。在这种情况下,只需要符号的总数。

    它的计算速度非常快:例如,对于 300 个符号,您将有一些使用 8 位,而另一些则使用 9 位。决定每种类型有多少的公式:

    9 位 : (300-256)*2 = 44*2 = 88 ; 8 位:300 - 88 = 212

    然后您可以根据需要分配数字(最好是使用 8 位的最频繁的数字,但这并不重要)。

    这个版本可以扩展到32位,基本上没有限制。

    【讨论】:

    • 一个元素的出现次数如何影响霍夫曼树的深度?只要有一个元素,您就必须将其关联为单个二进制序列,因此无论它在数字列表中出现多少次,都只会在树中出现一次。
    • 那就不再是霍夫曼了。 Huffman 的重点是为大多数出现的符号提供更少的位,以实现最佳压缩。从这个意义上说,霍夫曼树是最优的。
    • 是的,出现次数最多的符号位数更少,但无论是仅出现 10 次还是 3 524 578 次,它仍然会被相同的位序列替换。
    • 确实如此。即使一个符号具有“最多出现”属性,最重要的是知道它在总出现中的“份额”。出现 50% 时间的符号值得用 1 位来表示。而如果它只占总数的 0.4%,那么它应该用 8 位来表示。在这两种情况下,它都可以是“出现次数最多的符号”。
    • 嗯,这就是霍夫曼所做的,按出现的数量对元素进行排序,然后用位序列替换它们。并非所有元素都将替换为相同长度的位序列。我不想知道一个元素的出现次数,我只想知道在需要 32 位序列来存储下一个元素之前,可以用霍夫曼比特序列替换多少元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多