简体   繁体   中英

C - How to traverse a Huffman Tree and generate corresponding Huffman codes?

I'm currently working on a program that reads in text from standard input, creates a Huffman tree from the data, and then generates the Huffman codes for the symbols in the Huffman tree.

I'm able to create the Huffman tree, which consists of Tree Node structs that contain the symbol, the frequency of the symbol, the Huffman code for the symbol, and pointers to the let and right nodes. However, I'm kind of stuck on how to traverse the tree and modify each node's "code" according to where it is in the tree.

Essentially what I'm asking is how to traverse a binary tree while modifying a node's elements based on where it is in the tree.

Originally I tried something along the lines of:

void generateCodes (struct HuffTreeNode* root, unsigned long bitShift)
{
  struct HuffTreeNode* current = root;
  if (root != NULL)
  {
    current->code |= 0<<bitShift;
    generateCodes(root->left,bitShift+1);
    current->code |= 1<<bitShift;
    generateCodes(root->right,bitShift+1);

  }
}

However, that didn't work, and I'm kind of at a loss for what to try next. Any ideas?

You have formed the tree. SO now remains the traversing.

    17
    /\
   /  7
  /   /\
 10  /  3
 /\ C4  /\
A6 B4   D1 E2

Now initilaly you just put them( the 0's or 1's) in array.Left child link - 1 right child link-0

So in the array you put a[currrent]=1 then call huffmancode(tree->left,current+1)

OR if going to right subtree a[current]=0 then call huffmancode(tree->right,current+1) .

At reaching the leaf node print array.

Pseudocode: (printtree)

    if (root->left exists)
    {
        a[current] = 0;
        printtree(root->left, a, current + 1);
    }

    if (root->right exists)
    {
        a[current] = 1;
        printtree(root->right, a,current + 1);
    }


    if (root is leaf)
    {
        print a[].
    }

I assume that your tree is correctly (and optimally) built.

Each Huffman code is a path from the root to a leaf defining a symbol. You add a 0 when you traverse a left arc and a 1 when you traverse a right arc.

So, a way for getting a list of all the pairs symbol,code consists in traversing recursively the tree. You maintain the current path from the root to the current visited node and when you reach a leaf you generate the pair symbol (which would be stored in the leaf) and the current path.

A data structure for managing the current path is a stack.

So, an algorithm could be as follows:

void codes(struct Node * root, struct Stack * s)
{
  if (is_leaf(root))
    {
      char symbol = // symbol stored in the node
      char * code = // the reversed stack content; that is the code of current leaf
      printf("symbol %c has code %s\n", symbol, code);
    }

  s->push('0');
  codes(LLINK(root), s);
  s->pop();

  s->push('1');
  codes(RLINK(root), s);
  s->pop();
}

I leave to you the details of implementation of the stack and other meta-parts ( is_leaf() , LLINK(root) , ...).

You can improve the algorithm to generate bits

I hope will be helpful

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