Pagini recente » Cod sursa (job #317275) | Cod sursa (job #2573254) | Cod sursa (job #892202) | Cod sursa (job #1261067) | Cod sursa (job #2638593)
#include <fstream>
#include <cstdint>
#include <list>
#include <vector>
#include <queue>
#include <functional>
#include <unordered_map>
struct Huffman {
struct Encoding {
uint64_t val;
uint32_t len;
};
using FrequencyType = uint64_t;
using ElementType = uint32_t;
using EncodingType = Encoding;
struct Node {
Node* left = nullptr;
Node* right = nullptr;
FrequencyType freq;
Node(FrequencyType freq)
: freq(freq) {}
};
private:
uint64_t numCharacters;
std::vector<EncodingType> encodings;
uint64_t totalLength;
Huffman(uint64_t numCharacters) : numCharacters(numCharacters) {
encodings.reserve(numCharacters);
}
static uint64_t Traverse(Huffman& h, Node* node, const std::unordered_map<Node*, ElementType>& leaves, uint64_t currMask, uint32_t height) {
if ((node->left == nullptr) && (node->right == nullptr)) {
h.encodings[leaves.at(node)] = Encoding{currMask, height};
return height * node->freq;
} else {
const auto h1 = Traverse(h, node->left,leaves, currMask << 1, height + 1);
const auto h2 = Traverse(h, node->right,leaves, (currMask << 1) | 1, height + 1);
return h1 + h2;
}
}
public:
uint64_t NumCharacters() const { return numCharacters; }
uint64_t TotalLength() const { return totalLength; }
EncodingType EncodingFor(ElementType el) const { return encodings[el]; }
static Huffman Construct(std::ifstream& f) {
std::list<Node> nodes;
Node* root = nullptr;
uint64_t numNodes;
f >> numNodes;
std::queue<Node*> q1, q2;
Huffman h{numNodes};
std::unordered_map<Node*, ElementType> leaves;
leaves.reserve(numNodes);
auto newNode = [&](FrequencyType freq) -> Node* {
nodes.emplace_back(freq);
return &nodes.back();
};
for (uint32_t i = 0u; i < numNodes; ++i) {
FrequencyType freq;
f >> freq;
Node* leaf = newNode(freq);
leaves[leaf] = i;
q1.push(leaf);
}
auto popQueue = [] (std::queue<Node*>& q) -> Node* {
if (q.empty()) {
return nullptr;
}
auto ret = q.front();
q.pop();
return ret;
};
auto popNode = [&]() -> Node* {
if (q1.empty()) {
if (q2.empty()) {
return nullptr;
}
return popQueue(q2);
}
if (q2.empty()) {
return popQueue(q1);
}
if (q1.front()->freq < q2.front()->freq) {
return popQueue(q1);
}
return popQueue(q2);
};
while (true) {
Node* left = popNode();
Node* right = popNode();
if (!right) {
root = left;
break;
}
Node* n = newNode(left->freq + right->freq);
n->left = left;
n->right = right;
q2.push(n);
}
h.totalLength = Traverse(h, root, leaves, 0u, 0);
return h;
}
};
int main() {
std::ifstream fin("huffman.in");
Huffman h = Huffman::Construct(fin);
std::ofstream fout("huffman.out");
fout << h.TotalLength() << '\n';
for (uint32_t i = 0; i < h.NumCharacters(); ++i) {
const auto encoding = h.EncodingFor(i);
fout << encoding.len << ' ' << encoding.val << '\n';
}
return 0;
}