哈夫曼树,又叫赫夫曼树什么其他的了,这个东西吧,主要用来对一组数据的出现概率来进行建数,这样可以使得概率大的放在前面,就使得调用简单一些,而概率小的就放到后面,其实就是对数据的一个优化处理了。
接下来我们就来看看怎么建树吧:
#include
#include
#include
typedef struct{
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree; /哈夫曼树的结构体定义,权重,父节点,左右孩子结点
typedef char **HuffmanCode; /这个是我们的哈夫曼编码的格式转换
一:建树
通过上表可知,首先我们对数据编号,并令其 parent ,lchild 和 rchild 初始化为 0,接下来我们通过每次选出最小的两个数据然后对其父节点进行编号,并对新生成的父节点的相关信息进行编辑,也就是它的权重,左右孩子结点,接下来继续找最小的就好了,遍历完了之后就能得到右边的这个表了,接下来就是哈夫曼编码了
看下图
我们可以知道左边排0,右边排0,再想到我们上面的排序方式,可以知道我们需要从后面往前面进行逆向的编码,所以我们可以定义一个字符数组(也就是前面做了类型转换的),然后从尾部开始往前面赋值。
接下来就让我们看看详细的代码吧(有点小长哦):
void HuffmanCoding(HuffmanTree HT,HuffmanCode *HC,int *w,int n){ /第一个定义的就是我们哈夫曼树,第二个是字符数组,第三个就是我们的权重数组了
HuffmanTree p;
int i,m,s1,s2,start,c,f;
char *cd; /定义一个字符数组来进行单个数据的编码存储
if(n<=1) return;
m = 2 * n -1; /m就是我们总的数据个数,包括非叶子结点
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode));
p = HT; /这里注意,要先分配空间,再进行传值,不然 p 是没有空间的
for(i = 0;i
scanf("%d",&w[i]);
}
for(i = 1;i<=n;++i,++w){ /这里就是把我们的初始数据进行编号
p[i].weight = *w; /因为前面我们定义的 w 是 *w 所以直接用++w就可以指向下一个数据了
p[i].parent=p[i].lchild=p[i].rchild = 0;
}
for( ;i<=m;++i) /然后再对后面的位置先初始化
p[i].weight=p[i].parent=p[i].lchild=p[i].rchild = 0;
for(i = n+1;i<=m;++i){ /这里就开始循环找最小值了
Select(HT,i-1,&s1,&s2); /select函数用于找两个最小值,在后面哦
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
printf(" weight parent lchild rchild");
for(i = 1;i<=m;i++)
printf("\n%8d %8d %8d %8d",HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);
*HC = (HuffmanCode)malloc((n+1)*sizeof(char*));
cd = (char*)malloc(n*sizeof(char));
cd[n-1] = '\0';
for(i = 1;i<=n;++i){
start = n-1;
for(c = i,f = HT[i].parent;f!=0;c = f, f = HT[f].parent)
if(HT[f].lchild == c) cd[--start] = '0';
else cd[--start] = '1';
(*HC)[i] = (char*)malloc((n-start)*sizeof(char));
strcpy((*HC)[i],&cd[start]);
}
for(i = 1;i<=n;i++){
printf("\n %4d 的哈夫曼编码为: %s ",HT[i].weight,(*HC)[i]);
}
free(cd);
}
二:select函数
通过上面我们知道你要写一个select函数,用来找到没有父节点的所有数据中的最小的两个,注意是没有父节点的,没有父节点代表什么,代表它还没有被找到过,因为找到过的的父节点都会被标号。
void Select(HuffmanTree HT, int k, int *s1, int *s2)
{
int a, b,i;
*s1 = *s2 = 0;
a = b = MAXVALUE;
for (i = 0; i <= k; i++)
{
if (HT[i].parent == 0)
{
if (HT[i].weight < a)
{
b = a;
a = HT[i].weight;
*s2 = *s1;
*s1 = i;
}
else if (HT[i].weight < b)
{
b = HT[i].weight;
*s2 = i;
}
}
}
}