Huffman树的建立:首先,穿件n个初始的Huffman树,每棵树值包含一个单一的叶结点,叶结点记录对应的字母。将这n棵树按照权重(如频率)大小顺序排为一列。接着,拿走前两棵树(权重最小的两棵树),再把它们标记为Huffman树的叶结点,把这两个叶结点标记为一个分支节点的两个子结点,而这个分支节点的权重就为两个叶结点权重的和。把所得的新树放回到序列中的适当位置,是的权重的顺序保持升序。重复上述步骤,直至序列中只剩下一个元素,则Huffman树建立完毕。
如下图所示:
抽象基类HuffmanNode:
template<typename E>class HuffmanNode{
public:
virtual ~HuffmanNode() {}
virtual int weight() = 0;
virtual bool isLeaf() = 0;
};
templateclass LeafNode :public HuffmanNode < E > {
private:
E it; //元素值
int wgt; //权重
public:
//构造函数
LeafNode(const E& val,int wg)
{
it = val;
wgt = wg;
}
int weight() { return wgt; } //返回权重
E val() { return E; } //返回元素值
bool isLeaf() { return true; } //返回就是叶结点
};
template
class IntlNode :public HuffmanNode < E > {
private:
HuffmanNode* lc; //左子结点
HuffmanNode* rc; //右子结点
int wgt; //权重
public:
//构造函数
IntlNode(HuffmanNode* l,HuffmanNode* r)
{
wgt = l->weight() + r->weight();
lc = l;
rc = r;
}
int weight() { return wgt; } //返回权重
bool isLeaf() { return false; } //不是叶结点
//返回左子结点和设置左子结点
HuffmanNode* left() const { return lc; }
void setLeft(HuffmanNode* l) { lc = l; }
//返回右子结点和设置右子结点
HuffmanNode* right() const { return rc; }
void setRight(HuffmanNode* r) { rc = r; }
};
template class heap{
private:
E* Heap; //堆序列的指针
int maxsize; //堆的最大容量
int n; //堆里面的元素数量
void siftdown(int pos)
{
while (!isLeaf(pos))
{
int j = leftchild(pos);
int rc = rightchild(pos);
if ((rc < n) && prior(Heap[j], Heap[rc]))
j = rc;
if (prior(Heap[j], Heap[pos])) return;
swap(Heap, pos, j);
pos = j;
}
}
public:
//构造函数
heap(E* h, int num, int max)
{
Heap = h; n = num; maxsize = max;s
buildHeap();
}
//返回对的大小
int size() const
{
return n;
}
//判断是否为叶节点
bool isLeaf(int pos) const
{
return (pos >= n / 2) && (pos < n);
}
//返回左节点
int leftchild(int pos) const
{
return 2 * pos + 1;
}
//返回右节点
int rightchild(int pos) const
{
return 2 * pos + 2;
}
//返回父节点
int parent(int pos) const
{
return (pos - 1) / 2;
}
//建堆
void buildHeap()
{
for (int i = n / 2 - 1; i >= 0; i--) siftdown(i);
}
//插入一个元素
void insert(const E& it)
{
assert(n < maxsize, "Heap is full");
int curr = n++;
Heap[curr] = it;
while ((curr != 0) && (prior(Heap[curr], Heap[parent(curr)])))
{
swap(Heap, curr, parent(curr));
curr = parent(curr);
}
}
//移除根节点
E removefirst()
{
assert(n > 0, "Heap is empty");
swap(Heap, 0, --n);
if (n != 0)siftdown(0);
return Heap[n];
}
//判断第一个参数是否再第二个参数之前
bool prior(E a, E b)
{
if (a > b) return true;
else return false;
}
//交换值
void swap(E* heap, int i, int j)
{
E temp;
temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}
};
template<typename E>
class HuffmanTree{
private:
HuffmanNode* Root; //根结点
public:
//构造叶结点
HUffmanTree(E& val, int wg)
{
Root = new LeafNode(val, wg);
}
//构造分支节点
HuffmanTree(HuffmanTree* l, HuffmanTree* r)
{
Root = new IntlNode(l->root(), r->Root());
}
~HuffmanTree() {}
//返回根结点
HuffmanTree* root() { return Root; }
//返回权值
int weight() { return Root->weight(); }
};
template<typename E>
HuffmanTree* buildHuffman(HuffmanTree** TreeArray, int count)
{
heap*>* forest = new heap*>(TreeArray, count, count); //建造一个最小堆
HuffmanTree<char> *temp1, *temp2, *temp3 = NULL; //三个Huffman树
while (forest->size() > 1)
{
temp1 = forest->removefirst(); //将前两个树组合起来
temp2 = forest->removefirst();
temp3 = new HuffmanTree(temp1, temp2);
forest->insert(temp3); //把新树放在堆的最后
delete temp1; //必须删除已用的树
delete temp2;
}
return temp3;
}