一、构造哈夫曼树
二、哈夫曼编码
构造哈夫曼树
哈夫曼树的存储:
typedef struct
{
int weight;//结点的权值
int parent, lchild, rchild;//节点的双亲、左孩子、右孩子的下标
}HTNode,*HuffmanTree;
算法思想:
1.初始化HT[1,2…2n-1]:lchild=rchild=parent=0;
2.输入初始n个叶子结点:置HT[1, n]的weight值
3.进行n-1次合并,依次产生n-1个结点HT[i],i=n+1…,2n-1
a) 在HT[1,…I-1]中选两个未被选过的两个最小结点HT[s1],HT[s2],s1,s2为两个最小节点的下标
b) xiugai修改HT[s1]和HT[s2]的parent值:
HT[s1].parent = i;
HT[s2].parent = i;
c)修改新产生的HT[i]
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
void createHuffmanTree(HuffmanTree& HT, int n)
{
if (n <= 1)
return;
//初始化
int m = 2 * n - 1;//哈夫曼树前n项为叶子结点,后n-1个为度为2的结点,共2n-1个结点
//下标从1开始,所有空间初始化为0
for (int i = 1; i <= n; ++i)
{
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
//初始化前n项叶子结点的权重
for (int i = 1; i <= n; i++)
{
cin >> HT[i].weight;
}
for (int i = n + 1; i <= m; i++)
{
int s1, s2;//两个最小权重的下标
Select(HT, i - 1, s1, s2);//找到最小的两个权重值对应的下标
//进行合并
HT[s1].parent = i;
HT[s2].parent = 1;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
}
哈夫曼编码
//哈夫曼编码
typedef char** HuffmanCode;//动态分配数组存储哈夫曼表
void CreatHuffmanCode(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;//从start开始指向最后,即编码结束符位置
int c = i;
int f = HT[i].parent;//f指向结点c的双亲结点
while (f != 0)//从叶子结点开始向上回溯,直到根节点
{
--start;//回溯一次start向前移动一个位置
if (HT[f].lchild == c)//若节点c是f的左孩子,则标记为0
cd[start] == '0';
else
cd[start] == '1';//若节点c是f的右孩子,则标记为1
//继续向上回溯
c = f;
f = HT[f].parent;
}
//为第i个字符编码分配空间
HC[i] = new char[n - start];
//将求得的编码从临时空间cd拷贝到HC的当前行中
strcpy(HC[i], &cd[start]);
}
delete cd;//释放临时空间
}