C 为什么哈夫曼树代码需要无符号字符

C 为什么哈夫曼树代码需要无符号字符,c,tree,huffman-code,C,Tree,Huffman Code,我正在尝试创建一棵哈夫曼树我读到的问题对我来说很奇怪,它如下所示: 鉴于以下数据结构: struct huffman { unsigned char sym; /* symbol */ struct huffman *left, *right; /* left and right subtrees */ }; 编写一个以二进制文件名为唯一参数的程序, 构建该文件的哈夫曼树,假设原子(基本 符号)是8位无符号字符,并打印树以及 字典。 分配只能使用

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

鉴于以下数据结构:

struct huffman
{
    unsigned char sym;              /* symbol */
    struct huffman *left, *right;   /* left and right subtrees */
};
编写一个以二进制文件名为唯一参数的程序, 构建该文件的哈夫曼树,假设原子(基本 符号)是8位无符号字符,并打印树以及 字典。
分配只能使用 malloc()和排序可以使用qsort()完成

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

  • 我们需要一个频率阵列(可以是
    Farray[]={……}
  • 对其进行排序并添加两个最小的节点以形成一棵树,直到它没有留下最后一个节点(即头部)

  • 现在的问题是:为什么以及在哪里需要这些无符号字符数据?(这个问题需要什么类型的无符号字符数据,我认为只有频率才足以显示哈夫曼树)

    我这么做已经有一段时间了,但我认为生成的“字典”需要对数据进行编码,而“树”则用于对数据进行解码。当然,您总是可以从另一个构建一个


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

    如果您纯粹想显示树的形状,那么是的,您只需要构建它。然而,为了使其具有任何用途,您需要知道每个节点所代表的原始符号

    假设您的输入符号是[ABCD]。想象中的哈夫曼树/字典可能如下所示:

             ( )
            /   \              A = 1
          ( )   (A)            B = 00
         /   \                 C = 010
       (B)   ( )               D = 011
            /   \
          (C)   (D)
    
             ( )
            /   \              A = ?
          ( )   ( )            B = ?
         /   \                 C = ?
       ( )   ( )               D = ?
            /   \
          ( )   ( )
    
    如果不存储
    sym
    ,它看起来如下所示:

             ( )
            /   \              A = 1
          ( )   (A)            B = 00
         /   \                 C = 010
       (B)   ( )               D = 011
            /   \
          (C)   (D)
    
             ( )
            /   \              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()
    也不使用文件名作为参数,但这不是我的家庭作业;)

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

    • 评估给定符号出现在流中的概率,换句话说,评估符号出现在数据集中的频率
    • 一旦你研究了这些事件并用与概率相关的符号创建了表,你需要根据符号的概率对它们进行编码,为了实现这一神奇,你创建了一个字典,因为原来的符号往往被另一个小得多的符号所取代,尤其是对于数据集中经常使用的符号,字典会跟踪编码和解码阶段的这种替换。霍夫曼为您提供了一种算法,使这一过程自动化,并获得了相当好的结果
    实际上,它比这复杂一点,因为涉及到树,但主要目的始终是构建字典


    有一个完整的。

    假设我不需要打印字典,那么我需要8位无符号字符吗?这一行问题的确切含义是什么“编写一个以二进制文件名为唯一参数的程序,假设原子(基本符号)是8位无符号字符,构建该文件的哈夫曼树”这一点我无法理解,令人困惑,请帮忙解释一下me@user3085082无符号字符是您的输入数据:它们是您计算的频率。@Notlikethat所以您的意思是,作为唯一的参数,必须有一个名为file.txt的文件,其中必须包含类似于a=23 b=45 c=82等的内容。我说得对吗?您的意思是,如果我必须打印树,我只需要频率(比如FArray[]={…},然后对它们进行排序并添加最小节点)并打印出来,但如果我必须对其进行编码以找到压缩比、每个频率元素的长度等,那么我需要一个位无符号字符(这个问题要求我采用唯一的参数),我说的对吗?那么你的意思是,作为唯一的参数,必须有一个名为file.txt的文件,其中我必须有这样的内容a=23b=45c=82等等。我说的对吗?@user3085082不,该文件将包含“aaabccbbabababacab…”作为读取输入的一部分,您必须计算每个符号的频率。那么,如果我在文件中有这种类型的输入,那么我将如何计算符号“aaabccbbabccababacab…”的频率?频率应该由我们来创造哈夫曼树。它很安静confusing@user3085082分配一个字母表大小的整数数组(256)。将它们全部设置为零。对于从文件中读取的每个符号,将该符号的计数增加一。从文件中读取最后一个符号后,即为频率阵列。