【问题标题】:Choosing a compression algorithm to implement [closed]选择一种压缩算法来实现[关闭]
【发布时间】:2013-03-15 00:10:23
【问题描述】:

我接受了一些课程来实现我选择的压缩算法。它可以是任何语言,但我最了解的语言是 Java,其次是 C。它将基于 -

  1. 解压后的输出必须和原始输入匹配,所以只能看lossless的算法。

  2. 运行时间必须与消息的长度成正比。

  3. 内存要求必须与消息的长度无关。

我们的实现将进行如下测试 -

  1. 标准文本文件

  2. 字节值在 0-255 之间的二进制文件

  3. 大约 10mb 的未指定内容的大文件。

我最初的想法是使用动态算术编码,但我想知道是否有更适合上述约束的算法? 其次,用 C 语言而不是 Java 语言是更好的主意吗?我问这个是因为我认为 C 的内存占用会更小,但我不确定是否真的如此。

我花了一些时间在谷歌上搜索这个问题,一些网站提到了 LZW 编码与动态 Huf​​fman 编码的结合。这会是一个明智的追求途径吗?我们的讲师确实警告我们,多年来尝试动态霍夫曼编码的提交中有 90% 没有正确实施。

也就是说,我不怕尝试一下,但在开始之前我会重视一些意见。

任何反馈将不胜感激。

【问题讨论】:

  • 如果之前使用 Huffman 提交的 90% 都是错误的,那么这对您来说可能是一个更好的挑战。
  • Shannon-Fano 不满足您的 (3) 要求吗?做对很简单。如果您以前从未实现过压缩算法,我建议您使用 S-F。
  • 如果您确实走 LZW-Dynamic-Huffman 路线,我唯一的意见是使用接近-任何人的 LZW 技术除了提出的建议在Dr.Dobbs 1989 article。我发现对 Terry Welch 在算法中的“错误”的“分析”和作者对该问题的“解决方案”既侮辱了读者,也侮辱了 Welch 先生,坦率地说,他比那篇文章的作者忘记了更多关于数据压缩算法的事情永远都知道。
  • 不压缩,多买点磁盘空间。

标签: c encoding compression information-theory


【解决方案1】:

只有 LZW,没有其他编码,非常简单,而且工作得非常好。现在没有人会真正使用 LZW,因为还有其他算法可以更快地压缩。然而,对于一个任务,你无法击败 LZW 的简单性。没有霍夫曼,动态或其他。没有香农-法诺。没有算术或范围编码。是的,内存使用量与消息的长度无关。 Mark Nelson 写了一个very good explanation。

您可以在 C 或 Java 中执行此操作,但 C 可能不太容易出错,因为它具有无符号类型。

【讨论】:

    【解决方案2】:

    要回答我自己的问题,Shannon-Fano 对于这样的任务应该“足够好”。如果您从未在数据压缩领域做过任何事情,我建议您远离 Huffman 编码(或特殊版本的算术编码)。

    根据this,顺丰满足您的空间/时间要求。我建议首先实现类似的东西。伪代码如下:

     1:  begin
     2:     count source units
     3:     sort source units to non-decreasing order
     4:     SF-SplitS
     5:     output(count of symbols, encoded tree, symbols)
     6:     write output
     7:   end
     8:  
     9:  procedure SF-Split(S)
    10:  begin
    11:     if (|S|>1) then
    12:      begin
    13:        divide S to S1 and S2 with about same count of units
    14:        add 1 to codes in S1
    15:        add 0 to codes in S2
    16:        SF-Split(S1)
    17:        SF-Split(S2)
    18:      end
    19:  end
    

    只有在您彻底了解 SF(或者您之前已经实现过类似算法)的情况下,我才会建议您采用更严格的算术编码方法。我最近为一门信息理论课程实施了 SF,但在我理解它之前,它的某些部分似乎不直观且奇怪。在纸面上,它看起来很简单,但(与许多其他算法一样)可能具有欺骗性。

    除非你获得额外的“风格点数”,否则我个人会选择 Shannon-Fano。

    【讨论】:

    • 我不能使用 Shannon Fano 有几个原因。第一个是您必须将符号排序为非递增的概率顺序,因此您必须在文件中进行两次传递(一次用于分析,一次用于压缩)或将整个文件读入内存。第二个原因是它生成的树并不总是最优的。即使是静态霍夫曼编码也能产生更好的结果,而且实现起来并不难。
    • @Saf:我知道 SF 不是最优的,但最优不在你的清单上;)我检查了三次!将 10mb 完全读入内存应该不是问题;但如果你不能使用它,那就太糟糕了。这是对霍夫曼/算术编码的一个很好的介绍(因为它是后者的一个特例)。
    • 我可能会将其用作后备方案,或者甚至按照您的建议,作为起点。不过,我必须对文件进行两次扫描,加载整个文件会使内存需求与消息的长度成正比。我怀疑我会因为不得不扫描文件两次而被大量停靠,但我们的讲师往往都是关于最有效的路线。感谢您的指导。
    • 为什么人们把行号放在这些里面?
    • @RandyHoward:这是我链接的源的直接复制粘贴。
    【解决方案3】:

    内存限制建议使用某种自适应编码。算术编码很好。但是您没有指定有关性能的任何内容。该算法是否必须达到特定类别文件的任何性能目标?仅复制文件的算法满足上述要求,(但不会教你太多)。

    对于语言的选择,请使用您更熟悉的语言。将要执行很多位操作,因此 C 或 Java 都适合。您应该编写一些代码来处理将文件转换为比特流并再次返回,并将其作为一个单独的模块。我可以在 C 或 Java 中看到这样做。

    【讨论】:

    • 我们没有任何性能目标,除了“尽可能优化工作”,我知道含糊其辞,但我怀疑这是挑战的一部分。它应该适用于任何类型的文件,所以我们不必担心文件是音频还是视频等,除了可能检查我们是否最终没有信息扩展
    • 你应该在课堂上学到了没有无损压缩方法可以压缩所有文件的定理。但听起来他在要求某种标准方法。另请注意,允许输入文件 2 次通过(2 次仍然是成比例的)。只是不允许您将整个文件保存在内存中。
    • 课程只进行了一半,我们从算法开始,接下来将转向不同类型的文件,即 GIF、MP3 等。但这是一个好点,我会问讲师是否应该针对某种文件类型进行优化。
    猜你喜欢
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多