霍夫曼编码:为什么不需要分隔符?


17
Char        Code
====        ====
E           0000
i           0001
y           0010
l           0011
k           0100
.           0101
space       011
e           10
r           1100
s           1101
n           1110
a           1111

原文:

在湖附近看到怪异的眼睛

编码:
0000101100000110011100010101101101001111101011111100011001111110100100101

为什么在Huffman编码中不需要分隔符?


1
因为在解码二进制值时,您将“从左到右”的位块取为先匹配原始文本中的值的位。像在这种情况下,您会看到最左边的块(0000)与E匹配。如果字符代码中有任何值为000的符号,则可以用该符号替换000,然后再次从中的其余位开始搜索一种“从左到右”的方式。这就是为什么您不需要任何分隔。
Syed Ali Hamza

1
这个问题意味着通常需要分隔符。您已经知道不需要使用分隔符了Eerie eyes seen near lake(嗯,除了空格字符)。但是字符本身不需要分隔符。为什么不呢?
MSalters '16

尝试自己解码,永远不会有任何歧义。
njzk2

@MSalters:但是分离器通常需要具有可变长度的话:cat cheat for micecatch eat form ice。您的类比有缺陷:每个字母都是原子的;每个字母都是原子的。字母是微不足道的,并且本质上是可分离的。更好的类比是“当每个单词只有一条长长的,弯曲的,自相交的行时,为什么要阅读草书(手写)脚本?”,这甚至是一个糟糕的类比,因为您可以看一个手写的单词(甚至是其中的一部分)并识别出各个字母-如果您看不到开头,则霍夫曼编码的字符串会显得很乱。
G-Man说'Resstate Monica''Apr

@MSalters我看不出你的意思。我不需要字符分隔符,因为我们使用的是固定宽度编码:每个连续的八位块对应一个字符。但是霍夫曼编码不是固定宽度,因此是个问题。
David Richerby '16

Answers:


50

您不需要分隔符,因为霍夫曼代码是无前缀的代码(也无用的称为“前缀代码”)。这意味着没有代码字是任何其他代码字的前缀。例如,在您的示例中,“ e”的代码字是10,并且您可以看到没有其他代码字以数字10开头。

这意味着您可以通过从左到右读取编码的字符串并在看到代码字后立即输出一个字符来贪婪地进行解码。例如,0,00和000不编码任何内容,因此您可以继续读取位。当您读取0000时,它将编码为“ E”,并且由于该代码是无前缀的,因此您知道没有其他代码字0000x,因此现在可以输出“ E”并开始读取下一个代码字。同样,1不会编码任何东西,而10会编码“ e”。没有其他代码字以“ 10”开头,因此您可以输出“ e”。等等。


1
前缀代码通常也称为瞬时代码(例如,参见Cover和Thomas的信息论元素)。我认为“前缀代码”一词比无前缀代码出现的频率要高得多。
蝙蝠侠

3
还值得一提的是,为了对一系列级联的霍夫曼码进行解码,必须从一开始就赋予正确的码字边界。如果尝试在错误的码字边界解码该序列,则解码过程将生成错误的输出符号序列。
rwong

@rwong:如果霍夫曼代码开始时未正确同步,则它可能会无限期地继续输出错误的符号,但是任何时候错误地确定符号的长度,都会减少可能的错误状态。
超级猫

@supercat我想我会用不同的方式来表述:如果霍夫曼解码器最初设置在错误的码字边界并开始处理,则有可能(可能为零或任何东西,可能取决于字典和比特流内容),它可能会在有限时间内通过重合而落在正确的码字边界上,并且在发生这种情况时,它将为后续符号产生正确的解码结果。已经对可以保证这种重新同步的属性(在码字字典和比特流上)进行了一些研究。
rwong

@rwong:如果原始数据是随机分布的,则流中的每个比特具有独立的概率为一或零,则不同步的概率超过N个符号将随N的增加呈指数下降。实际数据更有可能包含可能阻止重新同步的模式,但实际上,在100MB文本文件开头出现错误不太可能损坏所有100MB文本。
supercat

13

将其想象成一棵树很有帮助。您只需遍历树,直到遇到叶节点,然后从根目录重新启动。从执行霍夫曼编码的算法中,您可以看到这种结构是在流程中创建的。

https://zh.wikipedia.org/wiki/File:HuffmanCodeAlg.png


6
这里重要的一点是所有有效的代码字都是叶子。如果内部节点上也有符号,则需要分隔符。
MvG

3

除E之外,没有其他代码以0000开头。除i以外,没有其他代码以0001开头。依此类推。在极端情况下,除e以外没有其他代码以01开头。您没有E = 0000,space = 000之类的东西,如果找到三个零,您将不知道该怎么办。

查看您的编码字符串:0000101100000 ...

您读取第一个零。您知道代码是E,i,y,l,k,逗号或空格之一。下一个零表示它不是k,逗号或空格,而是E,i,y或l。下一个零表示它是E或i。下一个零表示它是E。当您知道它是什么代码时,就知道您已经解析了该代码的所有位。

那么您有101100000 ... 1表示您有e,r,s,n或a。下一位是0,所以代码是e。同样,您已经完成了该角色。


-2

我们不能在Huffman编码中使用分隔符,因为每个字母的二进制等效项都不匹配任何字母的前缀代码,因此即使不使用分隔符也可以做到这一点。


3
我不是已经这么说过了,只是没有许多嵌套否定的令人困惑的层次。(顺便说一句,并不是我们不能使用分隔符;只是我们不需要。)
David Richerby
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.