CSP初赛-哈夫曼树

题目一:

字母表 {a, b, c, d, e} 的频率分别为 10%,15%,30%,16%,29%。若使用哈夫曼编码方式对字母进行不定长的二进制编码,字母 d 的编码长度( )位。

选项:
A. 1
B. 2
C. 2 或 3
D. 3

题目二:

字符 {a, b, c, d, e, f} 的频率分别为 5%, 9%, 12%, 13%, 16%, 45%。请问以下哪个选项是字符 a、b、c、d、e、f 分别对应的一组哈夫曼编码?

选项:
A. 1111, 1110, 101, 100, 110, 0
B. 1010, 1001, 1000, 011, 010, 00
C. 000, 001, 010, 011, 10, 11
D. 1010, 1011, 110, 111, 00, 01


这里的“前缀无冲突”,就是在说前缀码(prefix-free code)
对任意两个不同的码字 \(x\neq y\)都不允许 \(x\)\(y\) 的前缀。这样解码时,从左到右读比特,一旦读到某个码字,就能立刻确定对应字符并输出(不用再看后面的比特)——这叫即时可译(instantaneous decoding)

为什么要“前缀无冲突”?

  • 即时解码:读到叶子(完整码字)就停,输出一个字符,继续从根读下一段,比特流可在线逐个符号解出。
  • 避免歧义:如果存在前缀关系,解码器在读到短码字时就会犹豫:这是一个完整符号,还是更长码字的开头?这会导致需要回看/前瞻,甚至可能造成不唯一解码。

用你题里的选项 A 来看

选项 A(按 a,b,c,d,e,f 顺序):
1111, 1110, 101, 100, 110, 0
它的长度分别是:a=4, b=4, c=3, d=3, e=3, f=1。检查“前缀无冲突”只需看有没有码字是另一码字的前缀

  • 0 的后面有没有以 0 开头的更长码字?没有(其它都以 1 开头或先导为 1)。
  • 1 开头的三位码:100,101,110 之间互不为彼此前缀;四位码 1110,1111 也互不为前缀;三位码也不是四位码的前缀(后三位不同)。
    因此它是前缀码,解码时一旦读到 0 就立刻输出 f;读到 1110 就立刻输出 b,等等,毫不含糊。

(顺便一提,哈夫曼算法总是产出前缀码;哈夫曼树里,只有叶子结点才对应码字,内部结点不会对应码字,这正是“前缀无冲突”的结构性保证。)

形象理解(用二叉树/字典树)

把每个码字当作从根出发:读 0 走左,读 1 走右。
“前缀无冲突” ⇔ 所有码字都在叶子上,且没有一个码字停在别的码字之上(即没有码字对应内部结点)。
一旦走到叶子就输出字符并回到根,继续读后面的比特。

一个“有冲突”的反例

假设有码集合 {0, 01, 111}

  • 这里 001 的前缀。
  • 当比特流是 01... 时,读到第一个 0,你不敢立刻输出,因为它也可能是更长的 01 的开头;这就不是即时的。更糟的是,在某些集合里还会引起不唯一解码(存在多种切分方式得到不同字符串)。

快速检查方法

  • 排序/逐对检查:看是否存在“短码字 = 长码字的前缀”。

  • Trie(字典树)法:把码字插入一棵二叉 Trie,插入过程中若:

    1. 走到一个已经是“叶(已作为码字终止)”的结点还想继续往下走,或
    2. 刚把当前结点标为“叶”,却发现它已有子结点,
      就说明存在前缀冲突。

额外小知识:Kraft 等式

对二进制前缀码,长度集合 \(\{l_i\}\) 必满足 Kraft 不等式
\(\sum 2^{-l_i} \le 1\)
选项 A 的长度是 $ {4,4,3,3,3,1}\(,计算 \)\tfrac{1}{16}+\tfrac{1}{16}+\tfrac{1}{8}+\tfrac{1}{8}+\tfrac{1}{8}+\tfrac{1}{2} = 1$,
等号成立,说明这是一棵“满”的前缀码树,也从侧面验证了“前缀无冲突”。

第一题:字母d的哈夫曼编码长度

要确定字母d的编码长度,需遵循哈夫曼编码的核心步骤(合并最小频率节点),具体过程如下:

步骤1:整理频率(按从小到大排序)

  • a: 10%,b: 15%,d: 16%,e: 29%,c: 30%

步骤2:逐步合并最小频率节点

  1. 第一次合并:最小的两个频率(a:10% + b:15%)= 25%,新节点为25%。
    剩余节点:d:16%,25%(a+b),e:29%,c:30%。
  2. 第二次合并:最小的两个频率(d:16% + 25%)= 41%,新节点为41%。
    剩余节点:e:29%,c:30%,41%(d+a+b)。
  3. 第三次合并:最小的两个频率(e:29% + c:30%)= 59%,新节点为59%。
    剩余节点:41%(d+a+b),59%(e+c)。
  4. 第四次合并:41% + 59% = 100%,完成树的构建。

步骤3:确定d的编码长度

在哈夫曼树中,每个叶子节点的编码长度等于其到根节点的路径长度(左支为0、右支为1,或反之,不影响长度)。d在第二次合并中作为叶子节点,路径需经过2个分支,因此编码长度为2位

答案:B

第二题:字符abcdef的哈夫曼编码验证

关键前提

  1. 哈夫曼编码是前缀编码(任一编码不是其他编码的前缀);
  2. 频率最高的字符编码最短,频率最低的编码最长(频率:f:45% > e:16% > d:13% > c:12% > b:9% > a:5%,对应编码长度应递减)。

选项逐一排除

  • 选项A:编码为1111(a)、1110(b)、101(c)、100(d)、110(e)、0(f)
    验证:①前缀性:无编码是其他编码的前缀;②长度匹配:f(1位,最高频) > e(3位)、d(3位)、c(3位) > b(4位)、a(4位,最低频),符合频率-长度递减关系。暂符合

  • 选项B:编码为1010(a)、1001(b)、1000(c)、011(d)、010(e)、00(f)
    验证:频率最高的f编码为2位,但e(16%)编码也为2位(与f相同),且d(13%)、c(12%)编码也为3位(与b、a的4位差距不匹配频率递减),不符合“最高频编码最短”原则。排除

  • 选项C:编码为000(a)、001(b)、010(c)、011(d)、10(e)、11(f)
    验证:频率最高的f编码为2位,但e(16%)编码也为2位(与f相同),且最低频的a、b编码为3位(应最长),但d(13%)、c(12%)编码也为3位(与a、b相同),不符合频率-长度对应关系。排除

  • 选项D:编码为1010(a)、1011(b)、110(c)、111(d)、00(e)、01(f)
    验证:频率最高的f编码为2位,但e(16%)编码也为2位(与f相同),且d(13%)、c(12%)编码为3位(应短于a、b的4位,符合),但“最高频f未获得最短编码(1位)”,不符合哈夫曼编码逻辑。排除

答案:A

答案:

1)关于 {a,b,c,d,e} 频率 10%、15%、30%、16%、29%,字母 d 的哈夫曼码长度:
合并过程:10+15→25;再 16+25→41;再 29+30→59;最后 41+59→100。
得到叶深度:a=3,b=3,c=2,d=2,e=2。
⇒ 选 B. 2

2){a,b,c,d,e,f} 频率 5%、9%、12%、13%、16%、45% 的一组哈夫曼编码:
合并:5+9=14;12+13=25;14+16=30;25+30=55;45+55=100。
叶深度可为:a=4,b=4,c=3,d=3,e=3,f=1。
在选项中,只有 A(a,b,c,d,e,f 对应 1111,1110,101,100,110,0)满足该长度分配且前缀无冲突。
⇒ 选 A

posted @ 2025-08-16 18:47  kkman2000  阅读(60)  评论(0)    收藏  举报