如何生成霍夫曼树的二进制代码表?

时间:2017-11-21 20:03:53

标签: c algorithm tree huffman-code

我想实现一个函数,它为huffman树中的每个char提供二进制代码。

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

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

提前致谢!

2 个答案:

答案 0 :(得分:3)

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

#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并且做正确的分支。

答案 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;
    }
}

然后,您只需为compute_code_table_for_node(tree, node, tree->head, 0)中的每个node致电tree

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