Hemos discutido la codificación Huffman en una publicación anterior. En esta publicación se discute la decodificación.
Ejemplos:
Input Data : AAAAAABCCCCCCDDEEEEE Frequencies : A: 6, B: 1, C: 6, D: 2, E: 5 Encoded Data : 0000000000001100101010101011111111010101010 Huffman Tree: '#' is the special character used for internal nodes as character field is not needed for internal nodes. #(20) / \ #(12) #(8) / \ / \ A(6) C(6) E(5) #(3) / \ B(1) D(2) Code of 'A' is '00', code of 'C' is '01', .. Decoded Data : AAAAAABCCCCCCDDEEEEE Input Data : GeeksforGeeks Character With there Frequencies e 10, f 1100, g 011, k 00, o 010, r 1101, s 111 Encoded Huffman data : 01110100011111000101101011101000111 Decoded Huffman Data geeksforgeeks
Para decodificar los datos codificados necesitamos el árbol de Huffman. Iteramos a través de los datos codificados en binario. Para encontrar el carácter correspondiente a los bits actuales, usamos los siguientes pasos simples.
- Comenzamos desde la raíz y seguimos hasta encontrar una hoja.
- Si el bit actual es 0, nos movemos al Node izquierdo del árbol.
- Si el bit es 1, nos movemos al Node derecho del árbol.
- Si durante el recorrido encontramos un Node de hoja, imprimimos el carácter de ese Node de hoja en particular y luego continuamos nuevamente la iteración de los datos codificados a partir del paso 1.
El siguiente código toma una string como entrada, la codifica y la guarda en una variable codificada. Luego lo decodifica e imprime la string original. El siguiente código realiza la codificación y decodificación completa de Huffman de datos de entrada dados.
Implementación:
CPP
// C++ program to encode and decode a string using // Huffman Coding. #include <bits/stdc++.h> #define MAX_TREE_HT 256 using namespace std; // to map each character its huffman value map<char, string> codes; // to store the frequency of character of the input data map<char, int> freq; // A Huffman tree node struct MinHeapNode { char data; // One of the input characters int freq; // Frequency of the character MinHeapNode *left, *right; // Left and right child MinHeapNode(char data, int freq) { left = right = NULL; this->data = data; this->freq = freq; } }; // utility function for the priority queue struct compare { bool operator()(MinHeapNode* l, MinHeapNode* r) { return (l->freq > r->freq); } }; // utility function to print characters along with // there huffman value void printCodes(struct MinHeapNode* root, string str) { if (!root) return; if (root->data != '$') cout << root->data << ": " << str << "\n"; printCodes(root->left, str + "0"); printCodes(root->right, str + "1"); } // utility function to store characters along with // there huffman value in a hash table, here we // have C++ STL map void storeCodes(struct MinHeapNode* root, string str) { if (root==NULL) return; if (root->data != '$') codes[root->data]=str; storeCodes(root->left, str + "0"); storeCodes(root->right, str + "1"); } // STL priority queue to store heap tree, with respect // to their heap root node value priority_queue<MinHeapNode*, vector<MinHeapNode*>, compare> minHeap; // function to build the Huffman tree and store it // in minHeap void HuffmanCodes(int size) { struct MinHeapNode *left, *right, *top; for (map<char, int>::iterator v=freq.begin(); v!=freq.end(); v++) minHeap.push(new MinHeapNode(v->first, v->second)); while (minHeap.size() != 1) { left = minHeap.top(); minHeap.pop(); right = minHeap.top(); minHeap.pop(); top = new MinHeapNode('$', left->freq + right->freq); top->left = left; top->right = right; minHeap.push(top); } storeCodes(minHeap.top(), ""); } // utility function to store map each character with its // frequency in input string void calcFreq(string str, int n) { for (int i=0; i<str.size(); i++) freq[str[i]]++; } // function iterates through the encoded string s // if s[i]=='1' then move to node->right // if s[i]=='0' then move to node->left // if leaf node append the node->data to our output string string decode_file(struct MinHeapNode* root, string s) { string ans = ""; struct MinHeapNode* curr = root; for (int i=0;i<s.size();i++) { if (s[i] == '0') curr = curr->left; else curr = curr->right; // reached leaf node if (curr->left==NULL and curr->right==NULL) { ans += curr->data; curr = root; } } // cout<<ans<<endl; return ans+'\0'; } // Driver program to test above functions int main() { string str = "geeksforgeeks"; string encodedString, decodedString; calcFreq(str, str.length()); HuffmanCodes(str.length()); cout << "Character With there Frequencies:\n"; for (auto v=codes.begin(); v!=codes.end(); v++) cout << v->first <<' ' << v->second << endl; for (auto i: str) encodedString+=codes[i]; cout << "\nEncoded Huffman data:\n" << encodedString << endl; decodedString = decode_file(minHeap.top(), encodedString); cout << "\nDecoded Huffman Data:\n" << decodedString << endl; return 0; }
Producción:
Character With there Frequencies e 10 f 1100 g 011 k 00 o 010 r 1101 s 111 Encoded Huffman data 01110100011111000101101011101000111 Decoded Huffman Data geeksforgeeks
Comparando el tamaño del archivo de entrada y el tamaño del archivo de salida:
Comparación del tamaño del archivo de entrada y el archivo de salida codificado por Huffman. Podemos calcular el tamaño de los datos de salida de forma sencilla. Digamos que nuestra entrada es una string «geeksforgeeks» y se almacena en un archivo input.txt.
Tamaño del archivo de entrada:
Input: "geeksforgeeks" Total number of character i.e. input length: 13 Size: 13 character occurrences * 8 bits = 104 bits or 13 bytes.
Tamaño del archivo de salida:
Input: "geeksforgeeks" ------------------------------------------------ Character | Frequency | Binary Huffman Value | ------------------------------------------------ e | 4 | 10 | f | 1 | 1100 | g | 2 | 011 | k | 2 | 00 | o | 1 | 010 | r | 1 | 1101 | s | 2 | 111 | ------------------------------------------------ So to calculate output size: e: 4 occurrences * 2 bits = 8 bits f: 1 occurrence * 4 bits = 4 bits g: 2 occurrences * 3 bits = 6 bits k: 2 occurrences * 2 bits = 4 bits o: 1 occurrence * 3 bits = 3 bits r: 1 occurrence * 4 bits = 4 bits s: 2 occurrences * 3 bits = 6 bits Total Sum: 35 bits approx 5 bytes
Por lo tanto, pudimos ver que después de codificar los datos hemos guardado una gran cantidad de datos. El método anterior también puede ayudarnos a determinar el valor de N, es decir, la longitud de los datos codificados.
Este artículo es una contribución de Harshit Sidhwa . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA