#include <iostream>
#include <queue>
#include <vector>
#include <string>
using namespace std;
struct Node {
char ch;
int freq;
Node * left, * right;
Node( char c, int f, Node* l = nullptr, Node* r = nullptr)
: ch( c) , freq( f) , left( l) , right( r) { }
} ;
struct Compare {
bool operator( ) ( Node* a, Node* b) {
return a- > freq > b- > freq;
}
} ;
void buildCodes( Node* root, string code, vector< pair< char ,string>> & codes) {
if ( ! root) return ;
if ( ! root- > left && ! root- > right)
codes.push_back ( { root- > ch, code} ) ;
buildCodes( root- > left, code + "0" , codes) ;
buildCodes( root- > right, code + "1" , codes) ;
}
string encode( string text, vector< pair< char ,string>> & codes) {
string res;
for ( char c : text)
for ( auto & p : codes)
if ( p.first == c)
res + = p.second ;
return res;
}
string decode( string s, Node* root) {
string res;
Node* cur = root;
for ( char b : s) {
cur = ( b == '0' ) ? cur- > left : cur- > right;
if ( ! cur- > left && ! cur- > right) {
res + = cur- > ch;
cur = root;
}
}
return res;
}
void printDOT( Node* root) {
if ( ! root) return ;
if ( root- > left) {
cout << "\" " << root- > ch << root- > freq << "\" -- \" "
<< root- > left- > ch << root- > left- > freq << "\" \n " ;
printDOT( root- > left) ;
}
if ( root- > right) {
cout << "\" " << root- > ch << root- > freq << "\" -- \" "
<< root- > right- > ch << root- > right- > freq << "\" \n " ;
printDOT( root- > right) ;
}
}
int main( ) {
string text = "cheprazovivan" ;
vector< Node* > nodes;
for ( char c : text) {
bool found = false ;
for ( auto & n : nodes) {
if ( n- > ch == c) {
n- > freq++ ;
found = true ;
break ;
}
}
if ( ! found)
nodes.push_back ( new Node( c, 1 ) ) ;
}
priority_queue< Node* , vector< Node* > , Compare> pq;
for ( auto n : nodes)
pq.push ( n) ;
while ( pq.size ( ) > 1 ) {
Node* a = pq.top ( ) ; pq.pop ( ) ;
Node* b = pq.top ( ) ; pq.pop ( ) ;
pq.push ( new Node( '\0 ' , a- > freq + b- > freq, a, b) ) ;
}
Node* root = pq.top ( ) ;
vector< pair< char ,string>> codes;
buildCodes( root, "" , codes) ;
cout << "Коди Хаффмана:\n " ;
for ( auto & p : codes)
cout << p.first << " : " << p.second << endl;
string enc = encode( text, codes) ;
cout << "\n ENCODED:\n " << enc << endl;
cout << "\n DECODED:\n " << decode( enc, root) << endl;
cout << "\n DOT:\n graph G {\n " ;
printDOT( root) ;
cout << "}\n " ;
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8cXVldWU+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxzdHJpbmc+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKc3RydWN0IE5vZGUgewogICAgY2hhciBjaDsKICAgIGludCBmcmVxOwogICAgTm9kZSAqbGVmdCwgKnJpZ2h0OwoKICAgIE5vZGUoY2hhciBjLCBpbnQgZiwgTm9kZSogbCA9IG51bGxwdHIsIE5vZGUqIHIgPSBudWxscHRyKQogICAgICAgIDogY2goYyksIGZyZXEoZiksIGxlZnQobCksIHJpZ2h0KHIpIHt9Cn07CgpzdHJ1Y3QgQ29tcGFyZSB7CiAgICBib29sIG9wZXJhdG9yKCkoTm9kZSogYSwgTm9kZSogYikgewogICAgICAgIHJldHVybiBhLT5mcmVxID4gYi0+ZnJlcTsKICAgIH0KfTsKCnZvaWQgYnVpbGRDb2RlcyhOb2RlKiByb290LCBzdHJpbmcgY29kZSwgdmVjdG9yPHBhaXI8Y2hhcixzdHJpbmc+PiYgY29kZXMpIHsKICAgIGlmICghcm9vdCkgcmV0dXJuOwoKICAgIGlmICghcm9vdC0+bGVmdCAmJiAhcm9vdC0+cmlnaHQpCiAgICAgICAgY29kZXMucHVzaF9iYWNrKHtyb290LT5jaCwgY29kZX0pOwoKICAgIGJ1aWxkQ29kZXMocm9vdC0+bGVmdCwgY29kZSArICIwIiwgY29kZXMpOwogICAgYnVpbGRDb2Rlcyhyb290LT5yaWdodCwgY29kZSArICIxIiwgY29kZXMpOwp9CgpzdHJpbmcgZW5jb2RlKHN0cmluZyB0ZXh0LCB2ZWN0b3I8cGFpcjxjaGFyLHN0cmluZz4+JiBjb2RlcykgewogICAgc3RyaW5nIHJlczsKCiAgICBmb3IgKGNoYXIgYyA6IHRleHQpCiAgICAgICAgZm9yIChhdXRvICZwIDogY29kZXMpCiAgICAgICAgICAgIGlmIChwLmZpcnN0ID09IGMpCiAgICAgICAgICAgICAgICByZXMgKz0gcC5zZWNvbmQ7CgogICAgcmV0dXJuIHJlczsKfQoKc3RyaW5nIGRlY29kZShzdHJpbmcgcywgTm9kZSogcm9vdCkgewogICAgc3RyaW5nIHJlczsKICAgIE5vZGUqIGN1ciA9IHJvb3Q7CgogICAgZm9yIChjaGFyIGIgOiBzKSB7CiAgICAgICAgY3VyID0gKGIgPT0gJzAnKSA/IGN1ci0+bGVmdCA6IGN1ci0+cmlnaHQ7CgogICAgICAgIGlmICghY3VyLT5sZWZ0ICYmICFjdXItPnJpZ2h0KSB7CiAgICAgICAgICAgIHJlcyArPSBjdXItPmNoOwogICAgICAgICAgICBjdXIgPSByb290OwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXM7Cn0KCnZvaWQgcHJpbnRET1QoTm9kZSogcm9vdCkgewogICAgaWYgKCFyb290KSByZXR1cm47CgogICAgaWYgKHJvb3QtPmxlZnQpIHsKICAgICAgICBjb3V0IDw8ICJcIiIgPDwgcm9vdC0+Y2ggPDwgcm9vdC0+ZnJlcSA8PCAiXCIgLS0gXCIiCiAgICAgICAgICAgICA8PCByb290LT5sZWZ0LT5jaCA8PCByb290LT5sZWZ0LT5mcmVxIDw8ICJcIlxuIjsKICAgICAgICBwcmludERPVChyb290LT5sZWZ0KTsKICAgIH0KCiAgICBpZiAocm9vdC0+cmlnaHQpIHsKICAgICAgICBjb3V0IDw8ICJcIiIgPDwgcm9vdC0+Y2ggPDwgcm9vdC0+ZnJlcSA8PCAiXCIgLS0gXCIiCiAgICAgICAgICAgICA8PCByb290LT5yaWdodC0+Y2ggPDwgcm9vdC0+cmlnaHQtPmZyZXEgPDwgIlwiXG4iOwogICAgICAgIHByaW50RE9UKHJvb3QtPnJpZ2h0KTsKICAgIH0KfQoKaW50IG1haW4oKSB7CgogICAgc3RyaW5nIHRleHQgPSAiY2hlcHJhem92aXZhbiI7CgogICAgdmVjdG9yPE5vZGUqPiBub2RlczsKCiAgICBmb3IgKGNoYXIgYyA6IHRleHQpIHsKICAgICAgICBib29sIGZvdW5kID0gZmFsc2U7CgogICAgICAgIGZvciAoYXV0byAmbiA6IG5vZGVzKSB7CiAgICAgICAgICAgIGlmIChuLT5jaCA9PSBjKSB7CiAgICAgICAgICAgICAgICBuLT5mcmVxKys7CiAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKCFmb3VuZCkKICAgICAgICAgICAgbm9kZXMucHVzaF9iYWNrKG5ldyBOb2RlKGMsIDEpKTsKICAgIH0KCiAgICBwcmlvcml0eV9xdWV1ZTxOb2RlKiwgdmVjdG9yPE5vZGUqPiwgQ29tcGFyZT4gcHE7CgogICAgZm9yIChhdXRvIG4gOiBub2RlcykKICAgICAgICBwcS5wdXNoKG4pOwoKICAgIHdoaWxlIChwcS5zaXplKCkgPiAxKSB7CiAgICAgICAgTm9kZSogYSA9IHBxLnRvcCgpOyBwcS5wb3AoKTsKICAgICAgICBOb2RlKiBiID0gcHEudG9wKCk7IHBxLnBvcCgpOwoKICAgICAgICBwcS5wdXNoKG5ldyBOb2RlKCdcMCcsIGEtPmZyZXEgKyBiLT5mcmVxLCBhLCBiKSk7CiAgICB9CgogICAgTm9kZSogcm9vdCA9IHBxLnRvcCgpOwoKICAgIHZlY3RvcjxwYWlyPGNoYXIsc3RyaW5nPj4gY29kZXM7CiAgICBidWlsZENvZGVzKHJvb3QsICIiLCBjb2Rlcyk7CgogICAgY291dCA8PCAi0JrQvtC00Lgg0KXQsNGE0YTQvNCw0L3QsDpcbiI7CiAgICBmb3IgKGF1dG8gJnAgOiBjb2RlcykKICAgICAgICBjb3V0IDw8IHAuZmlyc3QgPDwgIiA6ICIgPDwgcC5zZWNvbmQgPDwgZW5kbDsKCiAgICBzdHJpbmcgZW5jID0gZW5jb2RlKHRleHQsIGNvZGVzKTsKICAgIGNvdXQgPDwgIlxuRU5DT0RFRDpcbiIgPDwgZW5jIDw8IGVuZGw7CgogICAgY291dCA8PCAiXG5ERUNPREVEOlxuIiA8PCBkZWNvZGUoZW5jLCByb290KSA8PCBlbmRsOwoKICAgIGNvdXQgPDwgIlxuRE9UOlxuZ3JhcGggRyB7XG4iOwogICAgcHJpbnRET1Qocm9vdCk7CiAgICBjb3V0IDw8ICJ9XG4iOwoKICAgIHJldHVybiAwOwp9