116 lines
2.8 KiB
C++
116 lines
2.8 KiB
C++
#include <iostream>
|
|
#include <map>
|
|
#include <queue>
|
|
#include <string>
|
|
|
|
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<char,int> 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<node, vector<node>, greater<node> > q;
|
|
for (map<char,int>::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<char,string>& 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<char,string> 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<char,string> table;
|
|
fill_encoding_table ("", trie, table);
|
|
for (map<char,string>::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 ...
|
|
}
|