C++ 哈夫曼二叉树的编码

C++ 哈夫曼二叉树的编码,c++,binary-tree,huffman-code,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

我正在尝试编写一个函数,它包含一个哈夫曼树和一个字符。然后它应该对字符进行编码并返回它

到目前为止的代码:

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

到目前为止,这还不起作用,调试也没有帮到我。有人能帮我一下吗,或者至少告诉我我的想法是否正确。

如果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
        }
     }
在节点没有离开的情况下,您必须要做一些事情。也许会复发

(根据注释)您可能正在使用哈夫曼树的一个变体,在该变体中,您可以保证每个节点要么是一个叶节点,要么有一个子叶节点。如果您可以保证这一点,那么上述情况就无关紧要(如果发生异常,最好抛出异常)。然而,现实世界中的哈夫曼树没有这个属性


当一个子元素是叶子而另一个子元素不是目标字母时,您将尝试为下一个循环设置新的
tempNode
tempLeft
tempRight

    else if ((tempRight->is_leaf()) && 
             (tempRight->letter != letter)) 
     {
         tempNode = root->left;
         tempLeft = tempNode->left;
         tempRight = tempNode->right;
         encode_str = encode_str + '0';
     } 
但是,由于从不修改
root
tempNode=root->left
将始终将
tempNode
设置为同一节点

您可能需要
tempNode=tempNode->left


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

tempLeft = tempNode->left;
tempRight = tempNode->right;
。。。成为
while()
循环中发生的第一件事


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

编写一个单元测试来建立你的树;验证树是否确实包含您希望它包含的内容;并用一个字母调用此函数。决定你认为执行应该如何进行。现在,在调试程序中运行代码,逐步执行。当它停止做你认为它应该做的事情时,你就能够解释为什么


实现哈夫曼编码的一种常见方法是使用叶节点数组,因此您可以通过简单的数组访问来访问该节点:

    NodePtr nodeA = nodes[0];
。。。每个节点中都有一个指向父节点的指针,以及一个指示它是左子节点还是右子节点的字段,这样您就可以轻松地从叶到根向后遍历树,构建代码(相反):


我以为根->左或根->右总是一片叶子?我就是基于这个。所以我的计划是检查它是否是leaf,看看这封信是否匹配。如果没有,它将沿着not leaf的“路径”继续并重试。如果!=字母?例如Wikipedia上的示例显示了具有两个非叶子树的节点:--但是您可能已经创建了一个具有您描述的特殊属性的树;在这种情况下,请按照我描述的调试步骤进行操作。我以为我是在使用tempNode=root->right;遍历树。那么新的tempnode将比以前的低一个节点。请参阅添加
root->left
永不更改。“一种常见的方式…叶节点数组”-如果要使用数组,那么简单地使用一个由字母索引的代码长度和代码值组成的数组或向量要快得多。我认为这里的目标是使用哈夫曼树,而不是实现一个高效的编码器。
    string code = "";
    NodePtr node = nodeA;
    while(node->parent != NULL) {
        code = node->code + code; 
        node = node->parent;
    }