Hoffmann encoding is a lossless data compression algorithm. In computer data processing, the Hoffmann encoding uses a variable length code table to encode the source symbol (such as a letter in a file, the variable length code table is obtained by evaluating the probability of occurrence of source symbols. Letters with high probability use short encoding, and letters with low probability use long encoding, this reduces the average length and expected value of the encoded string to achieve lossless data compression. For example, in English, E has the highest probability, while Z has the lowest probability. When an English article is compressed using the Hoffmann code, e is very likely to be represented by a bit, while Z may spend 25 BITs (not 26 ). Each English letter occupies one byte, that is, eight bits. E uses 1/8 of the general encoding length, and Z uses more than three times. If we can accurately estimate the probability of occurrence of each letter in English, we can greatly increase the proportion of lossless compression.
The construction of Hoffmann encoding mainly includes two parts:
1) construct the Hoffman tree based on the input string.
2) Facilitate the Hoffmann number and assign encoding to each character.
A Huffman tree is also called an optimal binary tree. It refers to a binary tree with the minimum length of the weighted path for a group of leaf nodes with fixed weights.
(1) path: the branch from one node in the tree to another node forms the path between two nodes. (2) path length: The Branch tree on the path. (3) path length of tree: The sum of the path length from the root node of the tree to each node. In a binary tree with the same number of nodes, the path length of the Complete Binary Tree is the shortest. (4) Weight of node: in some applications, assign a meaningful tree to the node in the tree. (5) Weight path length of node: the product of the length of the path from the node to the root node of the tree and the weight of the node. (6) weighted path length (WPL): Sum of the weighted path lengths of all leaf nodes in the tree
Steps for building the Hoffmann tree:
Algorithm: the input is a character array (N in length) without the same element and the occurrence frequency of the characters, and the output is the Harman tree.
Assume that there are n characters, then we can construct a Harman tree with N leaf nodes. The weights (frequencies) of n characters are set to W1, W2 ,..., Wn, then the construction rule of the Harman tree is:
(1) convert W1, W2 ,..., Wn is regarded as a forest with N trees (each tree has only one node). (2) the tree with the minimum weight of two root nodes is selected in the forest, as the Left and Right sub-trees of a new tree, and the root node weights of the new tree are the sum of the left and right sub-root node weights; (3) remove the selected two trees from the forest and add the new trees to the forest. (4) Repeat steps (2) and (3) until there is only one tree left in the forest, this tree is obtained by the user.
Use an example to understand the algorithm:
character Frequency a 5 b 9 c 12 d 13 e 16 f 45
Step 2: construct each element into a node, that is, a tree with only one element. And construct a minimum heap that contains all nodes. This algorithm uses the minimum heap as the priority queue.
Step 1: select two nodes with the smallest weight and add a node with the weight of 5 + 9 = 14 as their parent node. The minimum heap is updated. Now the minimum heap contains five nodes, four of which are the original nodes, and the nodes with the weights of 5 and 9 are merged into one.
Character Frequency C 12 d 13 Internal node 14 E 16 F 45
Repeat the preceding steps until the minimum Heap has only one node.
Character Frequency internal node 100
C language implementation:
# Include <stdio. h> # include <stdlib. h> # define max_tree_ht 100 // a Hoffman Tree node struct minheapnode {char data; // one character unsigned freq in the input character array; // number of occurrences of characters struct minheapnode * left, * right;}; // minimum heap: use struct minheap {unsigned size as the priority queue; // The minimum number of heap elements unsigned capacity; // maximum capacity struct minheapnode ** array;}; // initialize a minimum heap node struct minheapnode * newnode (char data, unsigned freq) {struct minheapnode * temp = (struct min Heapnode *) malloc (sizeof (struct minheapnode); temp-> left = temp-> right = NULL; temp-> DATA = data; temp-> freq = freq; return temp;} // create a minimum heap struct minheap * createminheap (unsigned capacity) {struct minheap * minheap = (struct minheap *) malloc (sizeof (struct minheap); minheap-> size = 0; // current size is 0 minheap-> capacity = capacity; minheap-> array = (struct minheapnode **) malloc (Minh EAP-> capacity * sizeof (struct minheapnode *); Return minheap;} // void swapminheapnode (struct minheapnode ** A, struct minheapnode ** B) {struct minheapnode * t = * A; * A = * B; * B = T;} // update the minimum heap. void minheapify (struct minheap * minheap, int idx) {int smallest = idx; int left = 2 * idx + 1; int right = 2 * idx + 2; if (left <minheap-> size & minheap-> array [left]-> freq <minheap-> array [smallest] -> Freq) smallest = left; If (right <minheap-> size & minheap-> array [right]-> freq <minheap-> array [smallest]-> freq) smallest = right; if (smallest! = Idx) {swapminheapnode (& minheap-> array [smallest], & minheap-> array [idx]); minheapify (minheap, smallest );}} // check whether the heap size is 1int issizeone (struct minheap * minheap) {return (minheap-> size = 1 );} // obtain the smallest node in the heap, struct minheapnode * extractmin (struct minheap * minheap) {struct minheapnode * temp = minheap-> array [0]; minheap-> array [0] = minheap-> array [minheap-> size-1]; -- minheap-> size; minheapify (minheap, 0); Re Turn temp;} // insert a node void insertminheap (struct minheap * minheap, struct minheapnode * minheapnode) to the minimum heap {++ minheap-> size; int I = minheap-> size-1; while (I & minheapnode-> freq <minheap-> array [(I-1)/2]-> freq) {minheap-> array [I] = minheap-> array [(I-1)/2]; I = (I-1)/2 ;} minheap-> array [I] = minheapnode;} // construct a minimum heap void buildminheap (struct minheap * minheap) {int n = minheap-> size-1; int I; fo R (I = (n-1)/2; I> = 0; -- I) minheapify (minheap, I);} void printarr (INT arr [], int N) {int I; for (I = 0; I <n; ++ I) printf ("% d", arr [I]); printf ("\ n ");} // check whether the leaf node int isleaf (struct minheapnode * root) {return! (Root-> left )&&! (Root-> right);} // create a minimum heap with size and insert the elements in data [] to the minimum heap struct minheap * createandbuildminheap (char data [], int freq [], int size) {struct minheap * minheap = createminheap (size); For (INT I = 0; I <size; ++ I) minheap-> array [I] = newnode (data [I], freq [I]); minheap-> size = size; buildminheap (minheap); Return minheap ;} // construct the Hoffman tree struct minheapnode * buildhuffmantree (char data [], int freq [], int size) {stru CT minheapnode * left, * right, * Top; // Step 4: create the minimum heap. struct minheap * minheap = createandbuildminheap (data, freq, size); // you know that the minimum Heap has only one element while (! Issizeone (minheap) {// Step 2: Obtain the smallest two elements left = extractmin (minheap); Right = extractmin (minheap); // Step 3: Based on the two smallest nodes, to create a new internal node // '$' is only a special identifier for the internal node. Top = newnode ('$ ', left-> freq + right-> freq); top-> left = left; top-> right = right; insertminheap (minheap, top);} // Step 3: the last remaining node is the following node: Return extractmin (minheap);} // print the Hoffmann code void printcodes (struct minheapnode * root, int arr [], int top) {If (root-> left) {arr [Top] = 0; printcodes (root-> left, arr, top + 1);} If (root-> right) {arr [Top] = 1; printcodes (root-> right, arr, top + 1);} // print if (isleaf (Root )) {printf ("% C:", root-> data); printarr (ARR, top) ;}// construct the Hoffmann tree, and print and print the huffmancodes (char data [], int freq [], int size) through traversal {// build the huffmantree struct minheapnode * root = buildhuffmantree (data, freq, size); // print the constructed Hoffmann tree int arr [max_tree_ht], Top = 0; printcodes (root, arr, top);} // test int main () {char arr [] = {'A', 'B', 'C', 'D', 'E', 'F'}; int freq [] = {5, 9, 12, 13, 16, 45}; int size = sizeof (ARR)/sizeof (ARR [0]); huffmancodes (ARR, freq, size); Return 0 ;}
The running result is as follows:
f: 0c: 100d: 101a: 1100b: 1101e: 111
Time Complexity
O (nlogn), where N is the number of characters. Extractmin () calls 2 * (n-1) times, And extractmin () is the complexity of log (n.