可变长度编码

在编码理论中，可变长度编码（variable-length code）是将源符号映射到可变位数的代码。计算机科学中的等效概念是位串。

可变长度编码可以允许源（source）以零错误（无损数据压缩）进行压缩和解压缩，并且仍然可以逐个符号地读回。通过正确的编码策略，可以将独立同分布的源压缩到几乎任意接近其熵的程度。这与固定长度编码方法相反，固定长度编码方法只能对大数据块进行数据压缩，并且任何超出可能性总数的对数的压缩都会带来有限（尽管可能任意小）的失败概率。

著名的可变长度编码策略包括霍夫曼编码、 Lempel-Ziv编码、算术编码和上下文自适应可变长度编码。

代码及其扩展 
代码的扩展是指通过将源序列的每个符号与原始代码产生的相应码字连接而获得的有限长度源序列到有限长度比特串的映射。

使用形式语言理论中的术语，精确的数学定义如下：令和是两个有限集，分别称为源字母表和目标字母表。一个代码表示一个全函数，将中的每一个符号映射到上的符号序列，并将扩展到和的同态 ，这自然地映射了每个源符号序列到目标序列，称为它的扩展。

可变长度编码的类别 
可变长度编码可以按照通用性递减的顺序严格嵌套，如非奇异码、唯一可解码代码和前缀代码。前缀码始终是唯一可解码的，后两者始终是非奇异的：

非奇异码 
如果每个源符号映射到不同的非空比特串，则代码是非奇异的，即从源符号到比特串的映射是单射。

 例如，映射不是非奇异的，因为“a”和“b”都映射到相同的位串“0”；此映射的任何扩展都会生成有损（非无损）编码。当一些信息丢失是可以接受的时候（例如当这样的代码用于音频或视频压缩时，其中有损编码变得等同于源量化），这样的单一编码可能仍然有用。
 然而，映射是非奇异的；它的扩展将生成无损编码，这对于一般数据传输很有用（但并不总是需要此功能）。请注意，非奇异代码不必比源代码更紧凑（并且在许多应用中，较大的代码是有用的，例如作为检测编码或传输错误和/或从编码或传输错误中恢复的方法，或者在安全应用程序，以保护源免受不可检测的篡改）。

唯一可解码代码 
如果代码的扩展是非奇异的 ，则该代码是唯一可解码的。给定的代码是否是唯一可解码的可以使用Sardinas-Patterson 算法来确定。

 映射是唯一可解码的（可以通过查看映射中每个目标位字符串后面的后续集来证明，因为一旦我们看到 0 位，位字符串就终止，该 0 位不能跟随任何现有代码来创建更长的有效代码，但能明确地开始一个新代码）。
 对于来自上一节的代码，该代码不是唯一可解码的，因为字符串011101110011可以解释为码字序列01110 – 1110 – 011 ，也可以解释为码字序列011 – 1 – 011 – 10011 。因此， cdb和babe给出了该编码字符串的两种可能的解码。然而，当所有可能的源符号的集合完全已知且有限时，或者当存在“确定该扩展的源元素是否可接受”的限制（例如形式文法）时，这样的代码是有用的。这些限制允许通过检查映射到同一符号的可能源符号中，哪些在这些限制下是有效的来解码原始消息。

前缀码 

如果映射中没有目标比特串是同一映射中不同源符号的目标比特串的前缀，则该代码是前缀码。这意味着符号可以在接收到整个码字后立即解码。此概念的其他常用名称包括无前缀代码、瞬时代码或上下文无关代码。

 上一段中的示例映射不是前缀码，因为我们在读取位串“0”后不知道它是否编码“a”源符号，或者它是否是编码“b”或“c”的前缀符号。
 前缀代码的示例如下所示。

 编码和解码示例：
  → 00100110111010 → |0|0|10|0|110|111|0|10| → 

前缀码的一个特例是块码。这里所有码字必须具有相同的长度。后者在信源编码中不是很有用，但通常在信道编码中用作前向纠错。

前缀码的另一个特殊情况是LEB128和可变长度数量(VLQ) 码，它们将任意大的整数编码为八位位组序列，即每个码字都是 8 位的倍数。

优点 
可变长度码的优点在于，不太可能出现的源符号會分配到较长的码字，而常出现的源符号會分配到较短的码字，从而给出较低的预期码字长度。对于上面的例子，如果 (a, b, c, d) 出现的概率为 ，使用上述编码表示源符号的预期位数为：

  

由于该源的熵为每个符号 1.7500 位，因此该编码能尽可能地压缩源，以便可以以零错误恢复源。

参见 

 哥伦布码
 克鲁斯卡尔计数
 可变长度指令集

参考

相关文献 

  (xii+191 pages) Errata 1Errata 2
  Draft available online 

编码理论