编码霍夫曼二进制树

时间:2014-02-19 16:35:50

标签: c++ binary-tree huffman-code

我正在尝试编写一个接受霍夫曼树和角色的函数。然后它应该对角色进行编码并将其返回。

到目前为止的代码:

string encode(NodePtr root, char letter)
{
    string encode_str; //a string which will store the encoded string
    NodePtr tempNode = root; //Initialize a new Huffman to be used in this function
    NodePtr tempLeft = root->left;
    NodePtr tempRight = root->right;

        //A while loop that goes on until we find the letter we want
        while((tempLeft->letter != letter) || (tempRight->letter != letter))
        {
         if((tempRight->is_leaf()) && (tempRight->letter == letter)) //check if is leaf and is letter
         {
                encode_str = encode_str + '1';
         }
         else if ((tempLeft->is_leaf()) && (tempLeft->letter == letter)) //check if is leaf and is letter
         {
             encode_str = encode_str + '0';
         }
         else if ((tempRight->is_leaf()) && (tempRight->letter != letter)) //check if is leaf and is NOT letter
         {
             tempNode = root->left;
             tempLeft = tempNode->left;
             tempRight = tempNode->right;
             encode_str = encode_str + '0';
         }
          else if ((tempLeft->is_leaf()) && (tempLeft->letter != letter)) //check if is leaf and is NOT letter
         {
             tempNode = root->right;
             tempLeft = tempNode->left;
             tempRight = tempNode->right;
             encode_str = encode_str + '1';
         }
         }    

    return encode_str;
}

到目前为止,这还没有奏效,调试对我也没有帮助。任何人都可以帮助我,或者至少告诉我我的想法是否正确。

1 个答案:

答案 0 :(得分:2)

如果tempLeft和tempRight都不是叶子,那么你就会有一个无限循环:

while((tempLeft->letter != letter) || (tempRight->letter != letter))
    {
        if((tempRight->is_leaf()) &&
           (tempRight->letter == letter)) 
        {
            // no
        }
        else if ((tempLeft->is_leaf()) &&
                 (tempLeft->letter == letter)) 
        {
            // no
        }
        else if ((tempRight->is_leaf()) && 
                 (tempRight->letter != letter)) 
        {
            // no
        }
        else if ((tempLeft->is_leaf()) && 
                 (tempLeft->letter != letter))
        {
            // no
        }
     }

在节点不是叶子的情况下,必须要做某些事情。也许递归?

(每条评论)您可能正在使用霍夫曼树的变体,您可以在其中保证每个节点都是叶子或有一个叶子。如果你可以保证,那么上面的内容并不重要(如果发生异常会抛出异常)。然而,现实世界的霍夫曼树没有这种属性。


当一个孩子是一片叶子而另一个孩子不是你的目标字母时,你会尝试设置一个新的tempNodetempLefttempRight,以便下一次循环。< / p>

    else if ((tempRight->is_leaf()) && 
             (tempRight->letter != letter)) 
     {
         tempNode = root->left;
         tempLeft = tempNode->left;
         tempRight = tempNode->right;
         encode_str = encode_str + '0';
     } 

但是,由于您从不修改roottempNode = root->left始终会将tempNode设置为同一节点。

您可能想要tempNode = tempNode->left


为避免重复代码,您可以移动

tempLeft = tempNode->left;
tempRight = tempNode->right;

...成为while()循环中发生的第一件事。


你说调试没有帮助。你真的在调试器中运行它吗?

编写一个设置树的单元测试;验证树实际上包含您想要的内容;并用一个字母调用此函数。决定你认为执行应该如何进行。现在在调试器中运行代码,逐步执行它。当它停止做你认为应该做的事情时,你就能够解释原因。


实现Huffman编码的一种常用方法是拥有一个叶子节点数组,这样您就可以通过简单的数组访问来访问节点:

    NodePtr nodeA = nodes[0];

...并且在每个节点中都有一个指向父节点的指针,以及一个指示它是左子节点还是右子节点的字段,这样您就可以轻松地从树到底遍历树,构建代码(在反向):

    string code = "";
    NodePtr node = nodeA;
    while(node->parent != NULL) {
        code = node->code + code; 
        node = node->parent;
    }