restructure and add ipi texs
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#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 ...
|
||||
}
|
||||
Reference in New Issue
Block a user