【问题标题】:How can i generate a binary code table of a huffman tree?如何生成霍夫曼树的二进制代码表?
【发布时间】:2018-05-05 10:14:01
【问题描述】:

我想实现一个函数,它为霍夫曼树中的每个字符提供一个二进制代码。

为了实现该功能,我尝试使用递归函数遍历表。但是我不知道如何为每个字符填充二进制代码的结果,以便函数返回一个包含所有字符和二进制代码的结构数组

我希望有人能指出我正确的方向。

先谢谢了!

【问题讨论】:

  • 感谢您的回复,但我不确定我是否理解。将指针隐藏在 typedef 中是什么意思?
  • tree_t 我猜(但这也可能是一个结构!)。您是否介意提供tree_t 的定义/类型定义,以便我们确定!
  • 啊,tree_t的定义给了,我会在问题里补充一下
  • @Stargateur,抱歉,我不想立即发布多行代码。我添加了 make_tree() 的定义。如果你错过了什么,我会添加它。
  • 我用minimal reproducible example 编辑您的问题,就像您看到的一样,您可以复制/粘贴,这将编译。

标签: c algorithm tree huffman-code


【解决方案1】:

好的,让我们看看一个可能的解决方案:

#include <stdint.h>

typedef struct code {
    size_t code_length;
    uint32_t code;
} code;

void compute_code_table(tree_t node, code *t, code c) 
{
    if (node->left == NULL) 
        t[node->letter] = c;
    else {
        c.code_length++;
        c.code <<= 1;
        compute_code_table(node->left, t, c);
        c.code += 1;
        compute_code_table(node->right, t, c);
    }
}

void code_print(code *c)
{
    size_t n = c->code_length;
    while (n --> 0)
        putchar('0' + ((c->code >> n) & 1));
}

int main(void)
{
    tree_t root = fixed_tree();
    code table[256] = { 0 };
    code c = { 0 };
    compute_code_table(root, table, c);

    for (size_t i = 0; i < 256; ++i) {
        if (table[i].code_length) {
            printf("%c\t", i);
            code_print(table + i);
            printf("\n");
        }
    }
}

基本上,这个想法是有一个在每一片叶子上都填满的桌子。在进行递归时,我们传递当前节点、表和当前代码。如果我们在叶子中,我们只需将代码存储在表中,否则我们需要执行递归:增加代码长度,在最低有效位添加 0 并执行左分支,然后将 0 更改为 1 并做正确的分支。

【讨论】:

    【解决方案2】:

    我会先让 compute_code_table 递归,这样你就可以轻松地遍历树。

    其次,它有助于每项任务或分配在线搜索一些解释(以伪代码或非伪代码)如何完成您的特定任务的资源。在这种情况下,这会产生以下解释:

    要生成霍夫曼代码,您需要遍历树到您指定的值 想要,每次取左手分支时输出 0,然后输出 1 每次你采取右手分支。 (通常你遍历 从您想要的代码向后树并构建二进制霍夫曼 也向后编码字符串,因为第一位必须从 顶部)。

    siggraph.org

    在 C 中,这可以这样实现:

    int compute_code_table_for_node(tree_t tree, node_t target_node, node_t current_node, int code_table) {
        // Check for target
        if ( current_node == target_node ) {
            // Found target
            return code_table;
        }
    
        // Check if end-node
        if ( current_node->left == NULL && current_node->right == NULL ) {
            // Is an end node
            return -1;
        }
    
    
        // Try left
        int left = compute_code_table_for_node(tree, target_node, current_node->left, code_table << 1 + 0);
    
        // Try right
        int right = compute_code_table_for_node(tree, target_node, current_node->right, code_table << 1 + 1);
    
        // Find which path was taken
        if ( left == -1 ) {
            // Left path didn't find it, so it must be the right path:
            return code_table << 1 + 1;
        } else {
            // Left path found it
            return code_table << 1 + 0;
        }
    }
    

    那么您只需为tree 中的每个node 调用compute_code_table_for_node(tree, node, tree-&gt;head, 0)

    这段代码不适用于您的具体情况,因此您必须重写它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多