霍夫曼解码算法

Huffman Decoding Algorithm

本文关键字:算法 解码 霍夫曼      更新时间:2023-10-16

解码时,我在构建霍夫曼树结构时遇到问题。

现在,我正在对树进行编码,如果它有子级作为前缀0,如果它没有子级,则将其作为1

例如,类似树的(a,b,c,d)将被编码为001a1b01c1d,并且它们的霍夫曼代码是

00|01|10|11

注:添加|是为了清楚起见,实际上不在标题中。

这是一个图形形式的树:

    / 
   / /
  a b c d

现在,当我尝试使用001a1b01c1d重建树时,我遇到的问题是正确地重建树,因为我不确定在返回树时要检查什么(向上走多远)。

Here is the code the index was only added just to try the word 'random' obviously it doesn't work for other cases. I am thinking of using the depth of the tree somehow

void Tree::build(std::queue<char> encodedHeader) {
    char currentChar;
    this -> thisRoot = new HCNode(0, '',0,0,0);
    HCNode * newRoot = new HCNode (0,'',0,0,0);
    HCNode * childZero = new HCNode (0, '', 0,0,0);
    HCNode * childOne = new HCNode (0, '', 0,0,0);
    childZero -> p = newRoot;
    childOne -> p = newRoot;
    newRoot -> c0 = childZero;
    newRoot -> c1 = childOne;
    this -> foreverRoot = newRoot;
    while(!header.empty()) {
        currentChar = header.front();
        header.pop();
        if(currentChar != 'n') {
            if (currentChar == '0') {
                HCNode * childZero = new HCNode (0, '', 0,0,0);
                HCNode * childOne = new HCNode (0, '', 0,0,0);
                child0 -> p = newRoot;
                child1 -> p = newRoot;
                newRoot -> c0 = childZero;
                newRoot -> c1 = childOne; 
                currentChar = header.front();
                while (currentChar == '0') {
                    newRoot = newRoot -> c0;
                    header.pop();
                    currentChar = header.front();
                    HCNode * childZero = new HCNode (0, '', 0,0,0);
                    HCNode * childOne = new HCNode (0, '', 0,0,0);
                    childZero -> p = newRoot;
                    childOne -> p = newRoot;
                    newRoot -> c0 = childZero;
                    newRoot -> c1 = childOne;  
                }
            }
            else {
                currentChar = header.front();
                header.pop();
                if(newRoot -> c0 != NULL) {
                    newRoot -> c0 -> symbol = currentChar;
                    newRoot = newRoot -> c1;
                }
                else {
                    newRoot -> symbol = currentChar;
                    while(newRoot -> p != NULL && index != 2) {
                        index++;
                        newRoot = newRoot -> p;
                    }
                    index = 0;
                    newRoot = newRoot -> c1;
                }
            }
        }
    }

我只是写了一些代码来做这项练习,而您使用的头格式与我使用的完全相同。我发现的诀窍是,这更容易递归实现,如:

Node read_tree(some_input input, string current_code = "") {
    Node node;
    if (input.readchar() == '0') {
        node.left = read_tree(input, current_code + "0");
        node.left.parent = node;
        node.right = read_tree(input, current_code + "1");
        node.right.parent = node;
    } else {
        node.code = input.readchar();
    }
    return node;
}

显然,你需要使用自己更现实的类型来做类似的事情,但基本的想法应该可行。

首先,我对我的英语感到非常抱歉(这不是我的母语:-)。一般来说,建议通过递归来解决树问题,这也是一个很好的建议。这是一个我认为可以工作的代码(我没有测试它,所以它可能需要一些工作):

buildTree(std::queue<char> header, HCNode* node)
{
     char currentChar = header.front();
     header.pop();
     if(currentChar == '0')
     {
          childZero -> p = newRoot;
          childOne -> p = newRoot;
          node->c0 = new HCNode (0, '', 0,0,0);
          node->c1 = new HCNode (0, '', 0,0,0);
          node->c0->p = node;
          node->c1->p = node;
          buildTree(header, node->c0); // this is the recurtion
          buildTree(header, node->c1); // this is the recurtion too
     }
     else // currentChar == '1'
     {
          currentChar = header.front();// currentChar = symbol
          header.pop();
          node-> symbol = currentChar;
     }
}
void Tree::build(std::queue<char> encodedHeader)
{
    this->foreverRoot = new HCNode(0, '',0,0,0);
    buildTree(header, foreverRoot);
}

我希望它会有帮助。祝你好运