#include<stdio.h>
typedef struct{ //节点的结构
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode; //动态分配数组存储哈夫曼编码表
//构造哈夫曼树,并求哈夫曼编码
HuffmanCode HuffmanCoding(HuffmanTree HT,HuffmanCode HC,int *w,int n){
HuffmanTree p;
int start;
unsigned f;
unsigned c;
char *cd;
int m,i,j,s1,s2,m1,m2;
if(n<=1)
return 0;
m = 2*n-1; //哈夫曼树共m个节点
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /* 0号单元未用 */
for(p = HT+1,i=1 ;i<=n; ++i,++p,++w){ //从一号到n号开始填表格
(*p).weight = *w; //赋权值
(*p).parent = 0;
(*p).lchild = 0;
(*p).rchild = 0;
}
for(;i<=m;++i,++p)
(*p).parent = 0; //从i从n+1到m 其余的节点双亲都是0
//开始建造哈夫曼树
for(i=n+1;i<=m;++i){
s1=s2=0;
m1 = m2 = 10000;
for(j=1;j<=i-1;j++){
if(HT[j].weight<m1 && HT[j].parent ==0){
m2 = m1; s2 = s1; //s1比s2要小
m1 = HT[j].weight; s1 = j;
}else if(HT[j].weight<m2 && HT[j].parent==0){
m2 = HT[j].weight;
s2 = j;
}
}
printf("\n%d,%d",s1,s2);
HT[s1].parent = HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight+HT[s2].weight;
}
//从叶子到根逆向求哈夫曼编码
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));//为第i个字符编码分配空间
strcpy(HC[i],cd+start); //从cd复制编码到HC cd+start是什么操作???
}
free(cd);
return(HC);
}
int main(){
HuffmanTree HT;
HuffmanCode HC;
int *w,n,i;
printf("please input the n:");
scanf("%d",&n);
w = (int*)malloc(n*sizeof(int));//动态生成n个存放权值的空间
for(i = 0;i<n;i++){
scanf("%d",w+i);
}
for(i=0;i<n;i++){
printf("%d ",w[i]);
}
HC = HuffmanCoding(HT,HC,w,n);//把输入的所有权值和共有n个数传进去,构造出哈夫曼树
for(i=1;i<=n;i++){
printf("\n %-3d %-8s",w[i-1],HC[i]);
//试着换一个逗号
}
}
输入的时候先输入共有多少个节点,在输入节点分别都是什么,输出先输出哈夫曼编码时每次找到最小两个数的序号,最后输出每个字符的哈夫曼编码。