#include #include #include #include using namespace std; // import namespace std // There are no general binary trees in the STL. // But we do not use much of this structure anyhow... struct node { struct node *left; struct node *right; char symbol; int weight; node (char c, int i) { // leaf constructor symbol = c; weight = i; left = right = 0; } node (node* l, node *r) { // internal node constructor symbol = 0; weight = l->weight + r->weight; left = l; right = r; } bool isleaf() {return symbol!=0;} bool operator> (const node &a) const { return weight > a.weight; } }; // construct the Huffman trie for this message node* huffman_trie (string message) { // count multiplicities map cmap; for (string::iterator i=message.begin(); i!=message.end(); i++) if (cmap.find(*i)!=cmap.end()) cmap[*i]++; else cmap[*i]=1; // generate leaves with multiplicities priority_queue, greater > q; for (map::iterator i=cmap.begin(); i!=cmap.end(); i++) q.push(node(i->first,i->second)); // build Huffman tree (trie) while (q.size()>1) { node *left = new node(q.top()); q.pop(); node *right = new node(q.top()); q.pop(); q.push(node(left, right)); } return new node(q.top()); } // recursive filling of the encoding table 'code' void fill_encoding_table (string s, node *i, map& code) { if (i->isleaf()) code[i->symbol]=s; else { fill_encoding_table (s+"0", i->left, code); fill_encoding_table (s+"1", i->right, code); } } // encoding string encode (map code, string& message) { string encoded = ""; for (string::iterator i=message.begin(); i!=message.end(); i++) encoded += code[*i]; return encoded; } // decoding string decode (node* trie, string& encoded) { string decoded = ""; node* node = trie; for (string::iterator i=encoded.begin(); i!=encoded.end(); i++) { if (!node->isleaf()) node = (*i=='0') ? node->left : node->right; if (node->isleaf()) { decoded.push_back(node->symbol); node = trie; } } return decoded; } int main () { string message = "ABRACADABRASIMSALABIM"; // generate Huffman trie node* trie = huffman_trie(message); // generate and show encoding table map table; fill_encoding_table ("", trie, table); for (map::iterator i=table.begin(); i!=table.end(); i++) cout << i->first << " " << i->second << endl; // encode and decode string encoded = encode(table, message); cout << "Encoded: " << encoded << " [" << encoded.size() << " Bits]" << endl ; cout << "Decoded: " << decode(trie, encoded) << endl; // the trie is not deleted here ... }