#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>
#include <memory>
#include <iomanip>
#include <cassert>
struct node;
using node_handle = std::unique_ptr<node>;
struct node
{
char data;
std::size_t frequency;
node_handle left;
node_handle right;
node(std::size_t freq) : data('\0'), frequency(freq) {}
node(char ch, std::size_t freq) : data(ch), frequency(freq) {}
bool operator<(const node& n) { return frequency < n.frequency; }
bool isLeaf() const { return left == nullptr && right == nullptr;}
};
std::vector<node_handle> extractHuffmanData(std::istream& is)
{
std::vector<node_handle> data;
std::size_t frequency;
char ch;
while (is >> ch >> frequency)
data.emplace_back(new node(ch, frequency));
return data;
}
node_handle buildHuffmanTree(std::vector<node_handle> data)
{
assert(data.size() > 0);
auto comp = [](const node_handle& a, const node_handle& b)
{
return *a < *b;
};
std::sort(data.begin(), data.end(), comp);
while (data.size() > 1)
{
node_handle a(data[0].release());
node_handle b(data[1].release());
data.erase(data.begin(), data.begin() + 2);
node_handle parent(new node(a->frequency + b->frequency));
parent->left.swap(a);
parent->right.swap(b);
auto pos = std::lower_bound(data.begin(), data.end(), parent, comp);
data.emplace(pos, parent.release());
}
return node_handle(data.back().release());
}
void print(const node_handle& node, std::size_t indent_level=0)
{
if (node == nullptr)
return;
const size_t indent_width = 2;
std::cout << std::setw(indent_width * indent_level) << "";
std::cout << node->frequency;
if (node->isLeaf())
std::cout << " - " << node->data << '\n';
else
{
std::cout << '\n';
print(node->left, indent_level + 1);
print(node->right, indent_level + 1);
}
}
int main()
{
std::istringstream is
{
"a 119\n"
"b 20\n"
"c 44\n"
"d 127\n"
};
auto huffmanData = extractHuffmanData(is);
auto huffmanTree = buildHuffmanTree(std::move(huffmanData));
print(huffmanTree);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgkKI2luY2x1ZGUgPGZzdHJlYW0+CiNpbmNsdWRlIDxzc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPiAgICAgICAKI2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPGlvbWFuaXA+CiNpbmNsdWRlIDxjYXNzZXJ0PgoKc3RydWN0IG5vZGU7CnVzaW5nIG5vZGVfaGFuZGxlID0gc3RkOjp1bmlxdWVfcHRyPG5vZGU+OwoKc3RydWN0IG5vZGUKewogICAgY2hhciBkYXRhOwogICAgc3RkOjpzaXplX3QgZnJlcXVlbmN5OwoKICAgIG5vZGVfaGFuZGxlIGxlZnQ7CiAgICBub2RlX2hhbmRsZSByaWdodDsKCiAgICBub2RlKHN0ZDo6c2l6ZV90IGZyZXEpIDogZGF0YSgnXDAnKSwgZnJlcXVlbmN5KGZyZXEpIHt9CiAgICBub2RlKGNoYXIgY2gsIHN0ZDo6c2l6ZV90IGZyZXEpIDogZGF0YShjaCksIGZyZXF1ZW5jeShmcmVxKSB7fQoKICAgIGJvb2wgb3BlcmF0b3I8KGNvbnN0IG5vZGUmIG4pIHsgcmV0dXJuIGZyZXF1ZW5jeSA8IG4uZnJlcXVlbmN5OyB9CgogICAgYm9vbCBpc0xlYWYoKSBjb25zdCB7IHJldHVybiBsZWZ0ID09IG51bGxwdHIgJiYgcmlnaHQgPT0gbnVsbHB0cjt9Cn07CgpzdGQ6OnZlY3Rvcjxub2RlX2hhbmRsZT4gZXh0cmFjdEh1ZmZtYW5EYXRhKHN0ZDo6aXN0cmVhbSYgaXMpCnsKICAgIHN0ZDo6dmVjdG9yPG5vZGVfaGFuZGxlPiBkYXRhOwoKICAgIHN0ZDo6c2l6ZV90IGZyZXF1ZW5jeTsKICAgIGNoYXIgY2g7CgogICAgd2hpbGUgKGlzID4+IGNoID4+IGZyZXF1ZW5jeSkKICAgICAgICBkYXRhLmVtcGxhY2VfYmFjayhuZXcgbm9kZShjaCwgZnJlcXVlbmN5KSk7CgogICAgcmV0dXJuIGRhdGE7Cn0KCm5vZGVfaGFuZGxlIGJ1aWxkSHVmZm1hblRyZWUoc3RkOjp2ZWN0b3I8bm9kZV9oYW5kbGU+IGRhdGEpCnsKICAgIGFzc2VydChkYXRhLnNpemUoKSA+IDApOwoKICAgIGF1dG8gY29tcCA9IFtdKGNvbnN0IG5vZGVfaGFuZGxlJiBhLCBjb25zdCBub2RlX2hhbmRsZSYgYikgICAgCiAgICB7IAogICAgICAgIHJldHVybiAqYSA8ICpiOyAKICAgIH07CgogICAgc3RkOjpzb3J0KGRhdGEuYmVnaW4oKSwgZGF0YS5lbmQoKSwgY29tcCk7CgogICAgd2hpbGUgKGRhdGEuc2l6ZSgpID4gMSkKICAgIHsKICAgICAgICBub2RlX2hhbmRsZSBhKGRhdGFbMF0ucmVsZWFzZSgpKTsKICAgICAgICBub2RlX2hhbmRsZSBiKGRhdGFbMV0ucmVsZWFzZSgpKTsKICAgICAgICBkYXRhLmVyYXNlKGRhdGEuYmVnaW4oKSwgZGF0YS5iZWdpbigpICsgMik7CgogICAgICAgIG5vZGVfaGFuZGxlIHBhcmVudChuZXcgbm9kZShhLT5mcmVxdWVuY3kgKyBiLT5mcmVxdWVuY3kpKTsKICAgICAgICBwYXJlbnQtPmxlZnQuc3dhcChhKTsKICAgICAgICBwYXJlbnQtPnJpZ2h0LnN3YXAoYik7CgogICAgICAgIGF1dG8gcG9zID0gc3RkOjpsb3dlcl9ib3VuZChkYXRhLmJlZ2luKCksIGRhdGEuZW5kKCksIHBhcmVudCwgY29tcCk7CiAgICAgICAgZGF0YS5lbXBsYWNlKHBvcywgcGFyZW50LnJlbGVhc2UoKSk7CiAgICB9CgogICAgcmV0dXJuIG5vZGVfaGFuZGxlKGRhdGEuYmFjaygpLnJlbGVhc2UoKSk7Cn0KCnZvaWQgcHJpbnQoY29uc3Qgbm9kZV9oYW5kbGUmIG5vZGUsIHN0ZDo6c2l6ZV90IGluZGVudF9sZXZlbD0wKQp7CiAgICBpZiAobm9kZSA9PSBudWxscHRyKQogICAgICAgIHJldHVybjsKCiAgICBjb25zdCBzaXplX3QgaW5kZW50X3dpZHRoID0gMjsKICAgIHN0ZDo6Y291dCA8PCBzdGQ6OnNldHcoaW5kZW50X3dpZHRoICogaW5kZW50X2xldmVsKSA8PCAiIjsKICAgIHN0ZDo6Y291dCA8PCBub2RlLT5mcmVxdWVuY3k7CgogICAgaWYgKG5vZGUtPmlzTGVhZigpKQogICAgICAgIHN0ZDo6Y291dCA8PCAiIC0gIiA8PCBub2RlLT5kYXRhIDw8ICdcbic7CiAgICBlbHNlCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8ICdcbic7CiAgICAgICAgcHJpbnQobm9kZS0+bGVmdCwgaW5kZW50X2xldmVsICsgMSk7CiAgICAgICAgcHJpbnQobm9kZS0+cmlnaHQsIGluZGVudF9sZXZlbCArIDEpOwogICAgfQp9CgppbnQgbWFpbigpCnsKICAgIHN0ZDo6aXN0cmluZ3N0cmVhbSBpcwogICAgewogICAgICAgICJhIDExOVxuIgogICAgICAgICJiIDIwXG4iCiAgICAgICAgImMgNDRcbiIKICAgICAgICAiZCAxMjdcbiIKICAgIH07CgogICAgYXV0byBodWZmbWFuRGF0YSA9IGV4dHJhY3RIdWZmbWFuRGF0YShpcyk7CiAgICBhdXRvIGh1ZmZtYW5UcmVlID0gYnVpbGRIdWZmbWFuVHJlZShzdGQ6Om1vdmUoaHVmZm1hbkRhdGEpKTsKCiAgICBwcmludChodWZmbWFuVHJlZSk7Cn0=