Pagini recente » Cod sursa (job #640847) | Cod sursa (job #446793) | Cod sursa (job #2793560) | Cod sursa (job #1241290) | Cod sursa (job #2638466)
#include <fstream>
#include <cstdint>
#include <list>
#include <vector>
#include <queue>
#include <functional>
struct Huffman {
struct Encoding {
uint64_t val;
uint64_t len;
};
using PriorityType = uint32_t;
using ElementType = uint64_t;
using EncodingType = Encoding;
struct Node {
enum class Type {
Regular,
Leaf
};
Node* left = nullptr;
Node* right = nullptr;
ElementType element = 0;
Type type;
PriorityType prio;
int height = 0;
Node(PriorityType prio)
: prio(prio)
, type(Type::Regular) {}
Node(PriorityType prio, ElementType element)
: prio(prio)
, element(element)
, type(Type::Leaf) {}
};
private:
int characters;
std::vector<EncodingType> encodings;
int totalHeight;
Huffman(int characters) : characters(characters) {
encodings.reserve(characters);
}
static int Follow(Huffman& h, Node* node, uint64_t currMask, uint64_t height) {
if (node->type == Node::Type::Leaf) {
h.encodings[node->element] = Encoding{currMask, height};
node->height = height;
return height;
} else {
const auto h1 = Follow(h, node->left, currMask * 2, height + 1);
const auto h2 = Follow(h, node->right, currMask * 2 + 1, height + 1);
return h1 + h2;
}
}
public:
int NumCharacters() const { return characters; }
int TotalHeight() const { return totalHeight; }
EncodingType EncodingFor(ElementType el) const { return encodings[el]; }
static Huffman Construct(std::ifstream& f) {
std::list<Node> nodes;
Node* root = nullptr;
int readNodes = 0;
int numNodes;
f >> numNodes;
struct Comp {
bool operator()(const Node* lhs, const Node* rhs) const {
return lhs->prio < rhs->prio;
}
};
std::priority_queue<Node*, std::vector<Node*>, Comp> q;
Huffman h{numNodes};
for (uint64_t i = 0u; i < numNodes; ++i) {
PriorityType prio;
f >> prio;
nodes.emplace_back(prio, ElementType{i});
q.push(&nodes.back());
}
while (true) {
Node* left = q.top();
q.pop();
if (q.empty()) {
root = left;
break;
}
Node* right = q.top();
q.pop();
const auto sumPrio = left->prio + right->prio;
nodes.emplace_back(sumPrio);
Node* newNode = &nodes.back();
newNode->left = left;
newNode->right = right;
q.push(newNode);
}
h.totalHeight = Follow(h, root, 0u, 0);
return h;
}
};
int main() {
std::ifstream fin("huffman.in");
Huffman h = Huffman::Construct(fin);
std::ofstream fout("huffman.out");
fout << h.TotalHeight() << '\n';
for (int i = 0; i < h.NumCharacters(); ++i) {
const auto encoding = h.EncodingFor(i);
fout << encoding.len << ' ' << encoding.val << '\n';
}
return 0;
}