哈弗曼树:即最优树,是一类带权路径长度最短的树。
哈夫曼树的存储表示:
typedef struct Node
{
int weight; //结点的权值
int parent,lchild,rchild; //结点的双亲、左孩子、右孩子的下标
}HTNode,*HuffmanTree; //动态分配数组存储哈弗曼树
构造哈弗曼树:
void CreateHuffmanTree(HuffmanTree& HT, int n)
{
int i, m, s1, s2;
m = 2 * n - 1; // 总结点的个数
HT = new HTNode[m + 1]; // 分配m+1个单元,HT[m]表示根节点
for (i = 1; i <= m; ++i) // 1 - n 存放叶子结点,初始化
{
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (i = 1; i <= n; ++i) //输入前n个单元中叶子结点的权值
{
cin >> HT[i].weight;
}
for (int i = n + 1; i <= m; ++i) // 通过n-1次的选择、删除、合并来创建哈夫曼树
{ // 在HT[1]~HT[i-1]的范围内选择两个parent为0且weight最小的两个结点,其序号分别赋值给 s1 s2
Select(&HT, i - 1, &s1, &s2);
HT[s1].parent = i; // 得到新结点i,删除s1、s2两个结点,将s1、s2的双亲域由0改为i
HT[s2].parent = i;
HT[i].lchild = s1; //s1和s2分别作为i的左右孩子
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight; // i的权值是左右孩子之和
}
}
根据哈弗曼树求哈夫曼编码:
void CreateHuffmanCode(HuffmanTree HT, HuffmanCode& HC, int n)
{
HC = new char* [n + 1];//分配存储n个字符编码的编码表空间
char*cd = new char[n];//分配临时存放每个字符编码的动态数组空间
cd[n - 1] = '\0';//编码结束符
for (int i = 1; i <= n; ++i) //逐个字符求哈夫曼编码
{
int start = n - 1, c = i, f = HT[f].parent;
while (f != 0)
{
--start; //回溯一次start向前指一个位置
if (HT[f].lchild == c) //c是f的左孩子,生成代码0,是右孩子,生成1
{
cd[--start] = '0';
}
else cd[--start] = '1';
c = f; //继续向前回溯
f = HT[f].parent;
}
HC[i] = new char[n = start];//为第i个字符编码分配空间
strcpy(HC[i], &cd[start]);//将求得的编码从临时空间cd复制到HC的当前行中
}
delete cd; //释放临时空间
}