CuPBoP/examples/huffman/huffTree.h

91 lines
2.0 KiB
C++

#include "stdio.h"
#include <algorithm>
#include <climits> // for CHAR_BIT
#include <iostream>
#include <iterator>
#include <map>
#include <math.h>
#include <queue>
using namespace std;
const int UniqueSymbols = 1 << CHAR_BIT;
void printBits(unsigned int val, int numbits) {
for (int i = numbits - 1; i >= 0; i--)
putchar('0' + ((val >> i) & 1));
}
typedef vector<bool> HuffCode;
typedef map<unsigned char, HuffCode> HuffCodeMap;
class INode {
public:
const int f;
virtual ~INode() {}
protected:
INode(int f) : f(f) {}
};
class InternalNode : public INode {
public:
INode *const left;
INode *const right;
InternalNode(INode *c0, INode *c1)
: INode(c0->f + c1->f), left(c0), right(c1) {}
~InternalNode() {
delete left;
delete right;
}
};
class LeafNode : public INode {
public:
const char c;
LeafNode(int f, char c) : INode(f), c(c) {}
};
struct NodeCmp {
bool operator()(const INode *lhs, const INode *rhs) const {
return lhs->f > rhs->f;
}
};
INode *BuildTree(unsigned int (&frequencies)[UniqueSymbols]) {
std::priority_queue<INode *, std::vector<INode *>, NodeCmp> trees;
for (int i = 0; i < UniqueSymbols; ++i) {
if (frequencies[i] != 0)
trees.push(new LeafNode(frequencies[i], (char)i));
}
while (trees.size() > 1) {
INode *childR = trees.top();
trees.pop();
INode *childL = trees.top();
trees.pop();
INode *parent = new InternalNode(childR, childL);
trees.push(parent);
}
return trees.top();
}
void GenerateCodes(const INode *node, const HuffCode &prefix,
HuffCodeMap &outCodes) {
if (const LeafNode *lf = dynamic_cast<const LeafNode *>(node)) {
outCodes[lf->c] = prefix;
} else if (const InternalNode *in =
dynamic_cast<const InternalNode *>(node)) {
HuffCode leftPrefix = prefix;
leftPrefix.push_back(false);
GenerateCodes(in->left, leftPrefix, outCodes);
HuffCode rightPrefix = prefix;
rightPrefix.push_back(true);
GenerateCodes(in->right, rightPrefix, outCodes);
}
}