English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

访客
1 / ?
返回课程列表

霍夫曼如何构建最优代码

Hamming 提出霍夫曼编码是一种贪心算法,它构建最小平均长度的前缀无关码。关键思想:从下向上构建树,总是合并两个概率最低的符号。

前向传递(构建)

1. 按概率从高到低排序所有符号。

2. 取两个概率最低的符号。将它们组合成一个新的元符号,其概率 = 两个符号的概率之和。

3. 在其排序位置插入元符号。

4. 重复,直到只剩两个符号。

5. 将0和1分配给剩余的两个符号。

后向传递(分配代码)

按相反顺序撤销合并:在每次分割时,被合并的两个符号接收与其组合父节点相同的前缀位,加上一个额外的0(一个子节点)或1(另一个子节点)。0/1的分配是任意的——要么有效。

霍夫曼构建:合并和解码树

为什么这是最优的:如果任何其他代码有较小的平均长度 L',应用相同的前向约简最终会产生两个符号,其平均长度小于1比特——对2符号代码不可能。矛盾。

追踪算法

Hamming的例子:四个符号 A, B, C, D,其中 p(A)=0.5, p(B)=0.25, p(C)=0.125, p(D)=0.125。

前向传递:

步骤1:排序:A(0.5), B(0.25), C(0.125), D(0.125)。最低两个:C, D。

步骤2:合并CD,p=0.25。新列表:A(0.5), B(0.25), CD(0.25)。

步骤3:最低两个:B(0.25), CD(0.25)。合并BCD,p=0.5。

步骤4:两个符号剩余:A(0.5), BCD(0.5)。分配 A=0, BCD=1。

后向传递:

BCD → B 得 10, CD 得 11。CD → C 得 110, D 得 111。

最终代码:A=0 (l=1), B=10 (l=2), C=110 (l=3), D=111 (l=3)。

L = 0.5·1 + 0.25·2 + 0.125·3 + 0.125·3 = 1.75 比特。

对以下符号应用霍夫曼算法:p(X1)=0.4, p(X2)=0.3, p(X3)=0.2, p(X4)=0.1。显示所有合并步骤、每个符号的最终代码,并计算 L。

多个有效的霍夫曼代码

Hamming 指出了非唯一性的两个来源:

1. 任意的0/1分配。 在每次分割时,你可以给任一子节点0。在整个过程中交换0和1给出一个具有相同 L 的不同代码。

2. 并列打破。 当两个节点具有相等的概率时,任一个都可以被放置得'更高'(先合并)。不同的并列打破选择可以产生结构不同的树——'长'vs'茂密'——具有相同的 L 但不同的代码长度分布。

长树与茂密树

长树(偏斜): 每个深度级别一个符号(Fibonacci类似结构)。代码长度差异很大:一个符号得到短代码,其他的级联到更长的代码。

茂密树(平衡): 符号在深度级别上均匀分布。代码长度聚集在平均值附近。较低的方差。

长树与茂密霍夫曼树

Hamming 的建议:当有选择时,优先选择茂密树。相同的 L,但代码长度的方差更小 → 更统一的解码时间 → 实时应用中更小的缓冲要求。

计算代码长度方差

代码长度的方差:Var = E[l²] − (E[l])²

对于代码 {A=0 l=1, B=10 l=2, C=110 l=3, D=111 l=3},其中 p=[0.5, 0.25, 0.125, 0.125]:

E[l] = L = 1.75

E[l²] = 0.5·1² + 0.25·2² + 0.125·3² + 0.125·3² = 0.5 + 1.0 + 1.125 + 1.125 = 3.75

Var = 3.75 − 1.75² = 3.75 − 3.0625 = 0.6875

等概率符号的替代茂密代码使用所有长度2的代码:L=2, Var=0。

考虑4个等概率符号(p=0.25每个)。计算 H。然后比较:(a) 茂密码 {00, 01, 10, 11},所有长度 = 2,和 (b) 长度为 {1, 2, 3, 3} 的长树代码。为每个计算 L 和 Var。你应该选择哪一个,为什么?

压缩收益与符号分布

Hamming 的规则:霍夫曼编码只在符号概率差异很大时才值得。

等概率。 如果所有2^k个符号都有相等的概率1/2^k,霍夫曼生成块码:每个符号得到长度k。L = H = k。没有优于简单块码的收益。

偏斜概率。 如果一个符号占主导(p >> 1/2^k对其他),霍夫曼给它分配一个非常短的代码(长度1或2),戏剧性地降低 L。

逗号码 (Hamming的术语)。当每个概率超过剩余总数的2/3时,霍夫曼自然产生:p(s1)→0, p(s2)→10, p(s3)→110, ...,直到最后两个等长代码。这是'逗号码':1后的尾0像逗号一样。

Hamming 注意到:现实数据压缩(备份、文件归档)当源具有偏斜概率时可以减少超过一半的存储——英文文本是主要例子。

霍夫曼与块代码:数值比较

Hamming 的第二个例子:p(s1)=1/3, p(s2)=1/5, p(s3)=1/6, p(s4)=1/10, p(s5)=1/12, p(s6)=1/20, p(s7)=1/30, p(s8)=1/30。

块码:8个符号 → 每个3比特 → L_block = 3。

Hamming 计算霍夫曼代码并报告 L_Huffman ≈ 2.58 比特。

节省:(3 − 2.58)/3 ≈ 14% 相对块编码的压缩。

当符号概率差异很大时(此处1/3对1/30,10:1比率),变长编码有很大的收益。

上述8符号源有 H ≈ 2.55 比特(你不需要验证这个)。Hamming 的霍夫曼代码达到 L ≈ 2.58 比特。块码使用 L = 3 比特。计算:(a) 霍夫曼代码的 L/H,(b) 块码的 L/H,(c) 这些比率告诉你每个编码相对于理论最小值的效率。

自编译程序

Hamming 以一个惊人的想法结束第11章:霍夫曼编码器可以编码自己。解码树(告诉解码器如何读取压缩消息)与压缩数据一起传输。接收方不需要事先知道代码。

编码器:对数据采样,估计概率,构建霍夫曼代码,将解码树编码为头部,然后对数据编码。

解码器:读取头部以重建树,然后使用它解码数据。

Hamming 的观点:这整个管道可以作为库函数运行,不需要人类参与。你调用它,它自动压缩和解压。现代归档格式(ZIP, gzip, bzip2)实现完全相同的模式。

更深层的原则:智能在于算法,而非固定的码表。算法适应它接收到的任何数据。这是 Hamming 在所有伟大工程系统中看到的模式:内置适应性,而非后来加上的。

Hamming 说自编译霍夫曼编码器'不需要人类干预或思考'。这个属性的工程优点是什么,它对算法设计有什么要求?给出一个现代系统的具体例子,它具有这个相同的原则。