为什么我们需要霍夫曼树代码的unsigned char

时间:2014-01-09 22:41:54

标签: c tree huffman-code

我正在尝试创建一个霍夫曼树,我读到的问题对我来说很奇怪,它如下:

  

鉴于以下数据结构:

struct huffman
{
    unsigned char sym;              /* symbol */
    struct huffman *left, *right;   /* left and right subtrees */
};
     

编写一个以二进制文件名称为唯一参数的程序,   假设原子(小学的)构建该文件的霍夫曼树   符号)是8位无符号字符,并打印树以及   字典。
  分配必须使用其他任何东西   malloc(),可以使用qsort()完成排序。

这让我感到困惑的是,编写一个程序来创建一个霍夫曼树,我们只需要做以下事情:

  1. 我们需要采用频率数组(可能是Farray[]={.......}
  2. 对它进行排序并添加两个最小的节点以形成树,直到它没有离开1个最终节点(即头部)。
  3. 现在的问题是:我们为什么以及在哪里需要那些未签名的char数据? (这个问题想要什么类型的unsigned char数据,我认为只有频率足以显示一个Huffman树)?

3 个答案:

答案 0 :(得分:2)

如果你纯粹想要显示树的形状,那么是的,你只需要构建它。但是,对于任何用途,您需要知道每个节点代表的原始符号。

想象一下你的输入符号是[ABCD]。想象中的霍夫曼树/字典可能如下所示:

         ( )
        /   \              A = 1
      ( )   (A)            B = 00
     /   \                 C = 010
   (B)   ( )               D = 011
        /   \
      (C)   (D)

如果您不存储sym,它看起来像这样:

         ( )
        /   \              A = ?
      ( )   ( )            B = ?
     /   \                 C = ?
   ( )   ( )               D = ?
        /   \
      ( )   ( )

不是很有用,是吗?

编辑2:计划中缺少的步骤是步骤0:从文件构建频率数组(不知怎的,我错过了你不需要实际编码文件)。这不是实际的霍夫曼算法本身的一部分,我找不到一个合适的例子来链接,所以这里有一个粗略的想法:

FILE *input = fopen("inputfile", "rb");
int freq[256] = {0};
int c;
while ((c = fgetc(input)) != EOF)
    freq[c]++;
fclose(input);

/* do Huffman algorithm  */
...

现在,仍然需要改进,因为它既不使用malloc()也不使用文件名作为参数,但它不是我的作业;)

答案 1 :(得分:0)

我这样做了一段时间,但我认为生成的“词典”需要编码数据,而“树”用于解码。当然,你总是可以从另一个构建一个。

在解码时,您遍历树(左/右,根据连续的输入位),当您点击终端节点(空指针)时,节点中的'sym'是输出值。

答案 2 :(得分:0)

通常数据压缩分为两大步骤;给出了一个数据流:

  • 评估给定符号在流中出现的概率,换句话说,您评估符号在数据集中出现的频率
  • 一旦你研究了出现并用符号与概率相关联来创建你的表,你需要根据它们的概率对符号进行编码,为了实现这个魔法,你创建了一个字典,原始符号经常被另一个符号替换掉它的大小要小得多,特别是对于数据集中经常使用的符号,字典会跟踪编码和解码阶段的这种替换。霍夫曼为您提供了一种自动化此过程的算法,并获得了相当不错的结果。

在实践中它比这更复杂,因为树涉及到,但主要目的始终是构建字典。

有一个完整的tutorial here