为什么 LZ77 实现不同?



我试图找到LZ77的正确实现,LZ77是1977年论文中最初的著名算法。我发现有许多不同的实现,它们产生不同的输出,但仍然标记为LZ77。例如,有些人使用哈希表,用于更"官方"的算法,如LZRW或LZJB。所以我很困惑。

我测试过的一些实现:

  1. https://gist.github.com/fogus/5401265 (C, 742> 538 字节, 哈希表?混乱输出(
  2. https://sourceforge.net/projects/crush(C++,742> 508 字节,哈希表?
  3. https://github.com/cstdvd/lz77(C,742> 642 字节 - 输出中包含可读 ASCII(
  4. http://lab.polygonpla.net/js/tinylz77.html(JS,742> 863 字节! --输出中包含可读的 ASCII(
  5. http://geocities.com/diogok_br/lz77/demo.html(JS,742> 658 字节 - 输出中包含可读的 ASCII(
  6. github.com/olle/lz77-kit/src/main/js/lz77.js(JS,742> 639 字节 - 输出中包含可读的 ASCII(
  7. https://github.com/Favrito/LZ77 (C, 742> 755 字节!!

据我所知,没有人使用任何后处理编码,如霍夫曼等。

我用来压缩的文本:

Oho! Oho! Rise up, O Teti!
Take your head, collect your bones,
Gather your limbs, shake the earth from your flesh!
Take your bread that rots not, your beer that sours not,
Stand at the gates that bar the common people!
The gatekeeper comes out to you, he grasps your hand,
Takes you into heaven, to your father Geb.
He rejoices at your coming, gives you his hands,
Kisses you, caresses you,
Sets you before the spirits, the imperishable stars...
The hidden ones worship you,
The great ones surround you,
The watchers wait on you,
Barley is threshed for you,
Emmer is reaped for you,
Your monthly feasts are made with it,
Your half-month feasts are made with it,
As ordered done for you by Geb, your father,
Rise up, O Teti, you shall not die!

它们都有不同的输出流。LZ77 没有纯粹的参考实现或标准需要检查吗?

为什么不是所有的"LZ77"压缩器都提供相同的压缩比,相同的输出比特流?

没有一种特定的方法可以实现 LZ77

LZ77 仅提供算法本身的一般数学概念。它的灵活性在于其参数可以更改,从而导致对编码器和解码器的不同要求,并且可以极大地影响生成的数据流。由实现来决定这些细节,例如缓冲区的大小以及代码字的构造方式。这些参数的敏感性是竞争实现可能称自己为 LZ77 但不兼容的原因。

例如,DEFLATE 规范指定 32768 窗口大小,并将位置和长度存储为 15+8 位码字。更简单但效率较低的实现可以选择 12 位距离和 4 位长度,给出 4096 字节的窗口大小。另一个可以选择 8192 字节的窗口大小,使用 13 位来表示距离,如果每个令牌使用 16 位,则只留下 3 位作为长度。

这种自由导致了其他方式的创新,例如LZSS引入文字标志,或使用哈希表的LZRW。另一个流行的创新是使用霍夫曼编码(如DEFLATE(或其他熵编码器跟进基于LZ的压缩,以提高压缩比。

最新更新