algorithm - 如何在具有 2N-1 + N*ceil(lg(n)) 位的一组符号 {0,1,2,..,N-1} 上传输霍夫曼码?

标签 algorithm

这是 Sedgewick 的书网站上的一个问题。他给出了“使用2N-1位来指定对应的trie的结构”的提示。

我可能不明白这个问题,尤其是他所说的 {0,1,2,..,N-1} 是什么意思。但我会使用 N 位来指定需要多少位来编码第 0、1 等代码,如下所示: 如果我们在第 i 个位置有 1,那么第 i 个代码使用 i 位,如果它有 0,则查看下一个有 1 的位置,第 (i+x) 个位置将指定位数(或查看如果下一个位置没有人,则在前一个位置(例如平衡二叉树给出))。

但这只有在编码特里接近完美时才有效,因为如果我们有频率的斐波那契分布,我们的编码特里将如下所示:

  o
 / \
o   o
   / \
  o   o
     / \
    o   o
 .....

这意味着我们总共将有 (n^2+n)/2-1 位,在长度描述位串之后(1+2+...+N 和 -1 的算术级数,因为 2 个节点具有相同的深度)。如何达到指定的空间复杂度?

这是一个链接:http://algs4.cs.princeton.edu/55compression/引用练习 20。

最佳答案

假设您有这些频率:

A 11
B 7
C 5
D 4
E 3
F 1

他们生成这个编码:

R: 0: 0:       B
      1:       C
   1: 0:       A
      1: 0:    D
         1: 0: E
            1: F

您可以使用数组 BCADEF 和将节点标识为终端 (0) 和非终端 (1) 的位序列描述此 trie 的结构,深度优先顺序:

11001010100

(第一个 110 表示 R: 0: 0: 路径 - root 是非终结符,0 也是非终结符,并且接下来的 0 是带有标签 B 的终端;接下来的 0 代表 1: 分支,它是另一个终端,标记为 C;接下来的 101:0: 分支,终止于 A;等等.) 这不是模棱两可的,因为霍夫曼编码是严格的二叉树 - 一个节点要么有两个 child ,要么没有。

您会注意到 11001010100 有 11 位,即 2 * 6 - 1,正如公式预测的那样。 (严格二叉树有N-1个内部节点和N个叶子)。

重构:

function restoreTree(alphabet, structure) {
  if (structure.shift() == "0") {
    return alphabet.shift();
  } else {
    var left = restoreTree(alphabet, structure);
    var right = restoreTree(alphabet, structure);
    return [left, right];
  }
}

var alphabet = "BCADEF".split('');
var structure = "11001010100".split('');
var tree = restoreTree(alphabet, structure);
document.body.textContent = JSON.stringify(tree);

编辑:N * ceil(lg(N)) 部分描述了字母表顺序的空间要求(假设字母表本身已知)。例如,假设您知道字母表是 "ABCDEF" - 位置从 0 到 5(A = 0,F = 5)。因此,每个位置都可以用三个位表示 (ceil(lg(6)) == 3,三个位足以表示 0..7)。因此,为了表示 “BCADEF” 顺序,您需要将 1、2、0、3、4、5 分别转换为三位:001010000011100101。这有 18 位,或 6 * ceil(lg(6))。从 "ABCDEF"001010000011100101 重建 "BCADEF" 应该很简单。

关于algorithm - 如何在具有 2N-1 + N*ceil(lg(n)) 位的一组符号 {0,1,2,..,N-1} 上传输霍夫曼码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34602904/

相关文章:

algorithm - 哈密​​顿路径 - 当每个顶点只能覆盖一次时,我可以覆盖边缘两次吗?

algorithm - 了解极小极大/极大极小路径 (Floyd-Warshall)

ruby - 理解递归回溯算法的 Ruby 实现

arrays - 给定排序的整数数组,写一个基于分治法的算法 A[i]=i

javascript - 如何从 JavaScript 中的字符串生成树

python - 仅使用国际象棋骑士的 Action 从一个图 block 移动到另一个图 block 的简单算法

python - 使用 Python 将记录存储在二叉树中

algorithm - C++ STL 集合和映射中的前序和后序遍历

c++ - 如何找到 vector 元素的乘积?

java - 使用快速排序对数组进行分区的运行时分析