简体   繁体   中英

Huffman Decoding Algorithm

I am having trouble building my structure of the Huffman tree when decoding.

Right now I am encoding the tree by if it has children making the prefix 0 and if it has no child make it 1 .

For example, a tree like (a,b,c,d) would be encoded as 001a1b01c1d and their Huffman code is

00|01|10|11

Note: | was added for clarity and is not actually in the header.

Here's the tree in a graphical form:

    / \
   /\ /\
  a b c d

Right now when I am trying to rebuild the tree using 001a1b01c1d , The problem I am having trouble is recreating the tree properly because I am unsure what to check for when going back up to the tree (how far to go up).

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,0);
    HCNode * newRoot = new HCNode (0,'\0',0,0,0);
    HCNode * childZero = new HCNode (0, '\0', 0,0,0);
    HCNode * childOne = new HCNode (0, '\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,0);
                HCNode * childOne = new HCNode (0, '\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,0);
                    HCNode * childOne = new HCNode (0, '\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;
                }
            }
        }
    }

I literally just wrote some code to do this as an exercise, and you're using the exactly same header format as I did. The trick I found was that this is much easier to implement recursively, as in:

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

Obviously you'll need to do something similar using your own more realistic types, but the basic idea should work.

first of all, i'm very sorry about my english (it's not my mother tongue :-). Generally it is recommended to solve trees problems by recursion and this is a good advice here too. here is a code that i think can be work (i didn't test it so maybe it will need a bit work):

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,0);
          node->c1 = new HCNode (0, '\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,0);
    buildTree(header, foreverRoot);
}

i'm hope it will be helpfull. good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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