Compression 哈夫曼算法中的角点情况

Compression 哈夫曼算法中的角点情况,compression,huffman-code,Compression,Huffman Code,我试图通过Huffman算法手动解决两种不同的压缩方案,在每种方案中,我们从一个有序队列开始,该队列包含元组(符号、频率),作为其项,我们将尝试形成一个字典: step 0: [c:3] [b:4] [a:5] step 1: [a:5] [7] [c:3] [b:4] step 2: [12] [a:5] [7] [c:3] [b:4] a -> 0 b -> 11 c -> 10 a -> 1 b -> 01 c

我试图通过Huffman算法手动解决两种不同的压缩方案,在每种方案中,我们从一个有序队列开始,该队列包含元组
(符号、频率)
,作为其项,我们将尝试形成一个字典:

step 0:
[c:3] [b:4] [a:5]

step 1:
[a:5]    [7]
     [c:3] [b:4]

step 2:
     [12]
[a:5]    [7]
     [c:3] [b:4]
a -> 0
b -> 11
c -> 10
a -> 1
b -> 01
c -> 00
如果我们认为左为0,右为1,则有字典:

step 0:
[c:3] [b:4] [a:5]

step 1:
[a:5]    [7]
     [c:3] [b:4]

step 2:
     [12]
[a:5]    [7]
     [c:3] [b:4]
a -> 0
b -> 11
c -> 10
a -> 1
b -> 01
c -> 00
直到现在,一切看起来都很好。但让我们假设我们的初始队列类似于以下内容:

step 0:
[c:1] [b:2] [a:4]

step 1:
    [3]      [a:4]
[c:1] [b:2]

step 2:
         [7]
    [3]      [a:4]
[c:1] [b:2]
这将生成以下词典:

step 0:
[c:3] [b:4] [a:5]

step 1:
[a:5]    [7]
     [c:3] [b:4]

step 2:
     [12]
[a:5]    [7]
     [c:3] [b:4]
a -> 0
b -> 11
c -> 10
a -> 1
b -> 01
c -> 00
这似乎是不对的(a
a
和b
b
都是相等的)


我做错了什么?我可以做一个
if
,在树的根上看哪个树枝实际上是一片叶子,选择这个方向作为1的方向,但这对我来说并不干净。我想我一定是遗漏了什么?

关键是字典中的位序列在解码时不应该引起歧义。序列的值无关紧要


在哈夫曼编码中,只有编码树中的叶子才能保存要编码的字符,从而解决了模糊性问题。上面的树遵循这一规则,因此产生的编码没有问题。

关键是字典中的位序列在解码时不应引起歧义。序列的值无关紧要


在哈夫曼编码中,只有编码树中的叶子才能保存要编码的字符,从而解决了模糊性问题。上面的树遵循此规则,因此结果编码没有问题。

位序列不相等。如果您有如下位字符串:

01100


然后只能将其解压缩为“bac”。您必须以一种保留序列中前导零的方式存储压缩结果,因此,例如,可以将上述内容填充到01100000或000011100,以填充输出的一个字节,然后与长度5一起存储。当然,问题只在于输出的第一个或最后一个字节,这取决于您选择填充哪一侧。

位序列不相等。如果您有如下位字符串:

01100


然后只能将其解压缩为“bac”。您必须以一种保留序列中前导零的方式存储压缩结果,因此,例如,可以将上述内容填充到01100000或000011100,以填充输出的一个字节,然后与长度5一起存储。当然,问题只在于输出的第一个或最后一个字节,这取决于您选择填充哪一侧。

在第二种情况下有一个问题,因为当将其编码为位时,“a”和“b”都将被编码为1。@EngluseDelysum:就像我说的,这是序列,而不是值。进行编码时,将用整个序列替换字符。所以“ab”-->101,“ba”-->011,“bb”-->0101,“aa”-->11@devouredelysiumaaa和bbb的编码不同:111和010101。如果你也存储序列的长度,它们就不一样了。在第二种情况下有一个问题,当将其编码为位时,“a”和“b”都将被编码为1。@EnglumeDelysum:正如我所说,这是序列,而不是值。进行编码时,将用整个序列替换字符。所以“ab”-->101,“ba”-->011,“bb”-->0101,“aa”-->11@devouredelysiumaaa和bbb的编码不同:111和010101。如果还存储序列的长度,则它们不相同。在写入实际文件时,我希望使用字节值,而不是显示的字符串。例如,在Java中,“a”(=1)和“b”(=01)都将退化为(字节)1,这意味着该字典是不明确的。或者我遗漏了什么?你不存储哈夫曼位序列的字节值,因为那样你会看到非常糟糕的压缩。相反,您必须尽可能将多个序列打包到同一字节中。通常,序列也在字节之间分割。例如,要压缩ABCABC,您需要存储10100101 00101000和长度15。我必须在最后添加一个0,以使其填充2个字节。因此,文件内容可能是字节0、15、165、40或十六进制000fa528,因此包含以2字节编码的长度和以下字节中的数据。这将为您提供8194字节的最大编码文件大小。@EngluseDelysum:仅添加到jjrv的注释中,当您使用哈夫曼编码对数据进行编码/压缩时,您将生成一个位流,而不是字节流。在写入实际文件时,我希望使用字节值,而不是显示的字符串。例如,在Java中,“a”(=1)和“b”(=01)都将退化为(字节)1,这意味着该字典是不明确的。或者我遗漏了什么?你不存储哈夫曼位序列的字节值,因为那样你会看到非常糟糕的压缩。相反,您必须尽可能将多个序列打包到同一字节中。通常,序列也在字节之间分割。例如,要压缩ABCABC,您需要存储10100101 00101000和长度15。我必须在最后添加一个0,以使其填充2个字节。因此,文件内容可能是字节0、15、165、40或十六进制000fa528,因此包含以2字节编码的长度和以下字节中的数据。这将为您提供8194字节的最大编码文件大小。@EngluseDelysum:只需添加到jjrv的注释中,当您使用哈夫曼编码对数据进行编码/压缩时,您将生成一个位流,而不是字节流。