简体   繁体   English

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

[英]How can i generate a binary code table of a huffman tree?

I want to implement an function which gives me a binary code for each char in a huffman tree. 我想实现一个函数,它为huffman树中的每个char提供二进制代码。

To implement the function i tried traversing the table by using a recursive function. 为了实现我尝试使用递归函数遍历表的函数。 However i don't know how to fill the result the binary code for each char so that the function returns an array of struct with all the chars and binary codes 但是我不知道如何为每个char填充结果二进制代码,以便函数返回带有所有字符和二进制代码的struct数组

I hope someone can point me in the right direction. 我希望有人能指出我正确的方向。

Thanks ahead! 谢谢!

Ok, let's see a possible solution: 好的,让我们看看一个可能的解决方案:

#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");
        }
    }
}

Basically the idea is to have a table which is filled at every leaf. 基本上,我们的想法是在每片叶子上放一张桌子。 While doing the recursion we pass the current node, the table and the current code. 在进行递归时,我们传递当前节点,表和当前代码。 If we are at a leaf we just store the code in the table, otherwise we need to perform the recursion: increase the code length, add a 0 in the least significant bit and do the left branch, then change that 0 to a 1 and do the right branch. 如果我们在一个叶子,我们只是将代码存储在表中,否则我们需要执行递归:增加代码长度,在最低有效位中添加0并执行左分支,然后将该0更改为1并且做正确的分支。

I would start by making compute_code_table recursive, this allows you to easily traverse the tree. 我首先使compute_code_table递归,这允许您轻松遍历树。

Secondly, it helps for every task or assignment to search online for some sources which explain (in pseudo-code or not) how to do your specific task. 其次,它有助于每个任务或任务在线搜索某些来源,这些来源解释(伪代码或非伪代码)如何执行您的特定任务。 In this case, this yields the following explanation: 在这种情况下,这会产生以下解释:

To generate a huffman code you traverse the tree to the value you want, outputing a 0 every time you take a lefthand branch, and a 1 every time you take a righthand branch. 要生成霍夫曼代码,您可以将树遍历到所需的值,每次使用左手分支时输出0,每次右手分支时输出1。 (normally you traverse the tree backwards from the code you want and build the binary huffman encoding string backwards as well, since the first bit must start from the top). (通常你从你想要的代码向后遍历树,并向后构建二进制霍夫曼编码字符串,因为第一位必须从顶部开始)。

siggraph.org siggraph.org

In C, this could be implemented as such: 在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;
    }
}

Then you only have to call compute_code_table_for_node(tree, node, tree->head, 0) for every node in the tree . 然后,你只需要调用compute_code_table_for_node(tree, node, tree->head, 0)为每一个nodetree

This piece of code won't work for your specific case, so you will have to rewrite it. 这段代码不适用于您的特定情况,因此您必须重写它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM