与霍夫曼解码树的奇怪的错误

时间:2013-11-28 07:46:53

标签: c++ algorithm debugging memory-management huffman-code

我之前提出了关于算法和实现的问题,但遇到了一个我无法解决的问题。

我能够从文本文件中获取前缀并将它们放入向量中,例如:

a 0
b 100
c 101
d 11

[0, a, 1, 0, 0, b, 1, 0, 1, c, 1, 1, d]

所以我的代码:

  • 以根节点
  • 开头
  • 遍历向量。如果我们得到0,则取当前节点并让它的左指针指向一个新节点。如果我们得到1,则取当前节点并让它的右指针指向一个新节点。如果它是一个字母,则将该字符存储到当前节点并从根目录开始。

(一个节点只保存一个值并有左右指针)

void Foo:: build(vector<char> v) {
    node* root = new node; 

    vector<char>:: iterator itr;

    node* current = root; 
    cout << " *" << endl;

    for(itr =  v.begin(); itr != v.end(); itr++) {
        cout << "(" << *itr << ")" << endl;

        if (!isdigit(*itr)) {
            current->value = *itr; 
            current = root; 
            cout << "*" << endl;
        }
        if (*itr == '0') {
            cout << "<-" << endl; 
            current->left = new node; 
            current = current->left; 
        }
        if (*itr == '1') {
            cout << "->" << endl; 
            current->right = new node; 
            current = current->right; 
        }
    }

    nodeVector.push_back(*root); 
}

。 如果你对couts感到好奇,*就意味着根源。所以对于'a',它将从根*开始,遇到0并且去&lt; - 左边将'a'放在该节点中,然后从根*开始。我这样做是为了看它是否像预期的那样左右移动,这似乎没问题。

 *
(0)
<-
(a)
*
(1)
->
(0)
<-
(0)
<-
(b)
*
(1)
->
(0)
<-
(1)
->
(c)
*
(1)
->
(1)
->
(d)
*

我遇到的问题很奇怪。唯一可行的字母是'a'和'd'。例如,root->left->value会给我'a',root->right->right->value会给'd',但root->right->left->right->value应该是'c'似乎不会放在节点中地点。当我尝试获取此值时,我的程序会崩溃。当我尝试解码一串位时,消息是不正确的,因为它只能做'd'和'a'。这让我怀疑这是树的建筑。任何建议都将受到高度赞赏!

2 个答案:

答案 0 :(得分:0)

在分配新节点之前,您需要检查之前是否已分配该路径。例如

if (*itr == '0') {
    cout << "<-" << endl;
    if (current->left) current = current->left;
                  else current = (current->left = new node);
}

答案 1 :(得分:0)

6502是正确的。

每次你的itteration循环通过时,你都在树下构建一个新路径。左边的那个很好,因为它永远不会被覆盖(但如果你有一个节点和2个叶子而不是它自己的叶子,它也会失败)。每次重新分配右侧的路径并覆盖创建的上一个节点,因此只有最后一个“d”条目可见。换句话说,“b”和“c”已创建,但每次创建新的右条目时,指向它们的指针都会丢失(覆盖)。

正如6502所指出的那样,您需要检查节点是否已经创建。但是你的代码可能会失败,因为空指针没有初始化为0,因此代码就像节点存在一样继续,但事实并非如此。对于每个 new node必须初始化空指针leftright,如果您打算测试它们的内容。例如:

if (*itr == '0') {
    cout << "<-" << endl;
    if (current->left) current = current->left;
    else
    {
        current = (current->left = new node);
        current->left = 0;  // initialize your empty pointers!
        current=>right = 0; // initialize your empty pointers!
    }
}

注意,放置指针初始化的更好的地方是new构造函数。