今天中秋节,同学都回家了,自己离家太远待在宿舍无聊就看看哈夫曼代码,顺手写了写,特此博客一篇,望多多指教:
对一组数进行哈夫曼树的构建:
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。[2]
代码如下:
void select(HuffmanTree ht,int n,int *s1,int *s2)
{
int min1 = INF;
int min2 = INF;
int i;
*s2 = 0;
*s1 = 0;
for(i = 1; i <= n; i++)
{
if(ht[i].weight <= min1 && ht[i].parent == 0)
{
min1 = ht[i].weight;
*s1 = i;
}
}
for(i = 1; i <= n; i++)
{
if(ht[i].weight <= min2 && ht[i].parent == 0 && i != *s1)
{
min2 = ht[i].weight;
*s2 = i;
}
}
}
void InitHuffman(HuffmanTree ht,int w[],int n)
{
int i;
int m;
for( i = 1; i <= n; i++)
{
ht[i].weight = w[i-1];
ht[i].parent = 0;
ht[i].LChild = 0;
ht[i].RChild = 0;
}
m = 2*n - 1;
for(i = n+1; i <= m; i++)
{
ht[i].weight = 0;
ht[i].parent = 0;
ht[i].LChild = 0;
ht[i].RChild = 0;
}
}
void CrtHuffmanTree(HuffmanTree ht,int w[],int n)
{
int s1,s2;
InitHUffman(ht,w,n);
for(i = n+1; i<= m; i++)
{
select(ht,i-1,&s1,&s2);
ht[i].weight = ht[s1].weight + ht[s2].weight;
ht[s1].parent = i;
ht[s2].parent = i;
ht[i].LChild = s1;
ht[i].RChild = s2;
}
}
这时候二叉树就构建成功了,如果想进行编码,则直接遍历每一个叶子节点就OK
得到编码
void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int n)
{
char *cd;
int i;
int c;
int start;
int p;
cd = (char*)malloc((n+1)*sizeof(char));
cd[n-1] = '\0';
for(i = 1; i <= n; i++)
{
start = n-1;
c = i;
p = ht[i].parent;
while(p != 0)
{
--start;
if(ht[p].LChild == c)
{
cd[start] = '0';
}
else
{
cd[start] = '1';
}
c = p;
p = ht[p].parent;
}
hc[i] = (char*)malloc((n-start)*sizeof(char));
strcpy(hc[i],&cd[start]);
}
}
同时祝自己中秋节快乐