#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<limits.h>
//定义宏常量,个数为4
#define N 4
//外面必须加上括号
#define M (2*N-1)
struct hafftree
{
int weight;//权重
int parent;//双亲节点
int left,right;//左孩子和右孩子
};
struct haffcode
{
char data;//定意数据的
int weight;//权重
char code[N];//存放数据的字符数组
};
typedef struct hafftree haffmantree[M];//定义一个hafftree的数组大小为M
typedef struct haffcode haffmancode[N];//定义一个代码的字符数组的大小N
void initCode(haffmancode hc) //对输入的代码进行操作
{
int i;
for(i=0; i<N; i++)
{
printf("请输入第%d个字符和它的权值",i+1);
fflush(stdin);//清空输入的缓冲区
scanf("%c%d",&hc[i].data,&hc[i].weight);//为其赋值
}
}
void initTree(haffmantree ht, haffmancode hc) //初始化哈弗哈树
{
int i;
for(i=0; i<N; i++)
{
ht[i].weight=hc[i].weight;//给ht的权值赋值
}
for (i=0; i<M; i++)
{
ht[i].parent=ht[i].left=ht[i].right=-1;//初始化值为-1
}
}
void createTree(haffmantree ht) //创建树
{
int i,j,min1,min2,index1,index2;//min1是最小值,min2是次小值,index是最小值的下标,index2是次小值的下标
for(i=N; i<M; i++) //找最小值和次小值
{
min2=min1=INT_MAX;//初始化min1和min2的前面导入头文件这是int的最大值
index1=index2=-1;//初始化下标为-1
for(j=0; j<i; j++) //随着i的变化而发生变化
{
if(ht[j].parent==-1)
{
//排除已经用过的值
if(ht[j].weight<min1)
{
min2=min1;//先将目前的最小给第二小
index2=index1;//赋值给index2
min1=ht[j].weight;//得到最小值
index1=j;//得到当前的下标
}
else if(ht[j].weight<min2)
{
min2=ht[j].weight;
index2=j;//当其他的小于min2
}
}
}
ht[i].weight=min1+min2;//存入新的节点
ht[i].left=index1;
ht[i].right=index2;//双亲节点存入左右孩子的下表
ht[index1].parent=ht[index2].parent=i;//给左右孩子赋值双亲的节点的下标
}
}
void ceratecode(haffmantree ht,haffmancode hc) //生成代码
{
char code[N];
int i,j,start;
for(i=0; i<N; i++)
{
start=N-1;
code[start]='\0';
j=i;
while(ht[j].parent!=-1)
{
code[--start]=ht[ht[j].parent].left==j?'0':'1';//判断是左孩子还是右孩子
j=ht[j].parent;//给它的位置赋值为双亲节点
}
strcpy(hc[i].code,&code[start]);//赋值给数组的元素
}
}
void printcode(haffmancode hc) //打印编码
{
int i;
for(i=0; i<N; i++)
{
printf("%c:%s\n",hc[i].data,hc[i].code);//打印输出
}
}
int main()
{
haffmancode hc;
haffmantree ht;
initCode(hc);//初始化haff的编码
initTree(ht,hc);//初始化haff树
createTree(ht);
ceratecode(ht,hc);
printcode(hc);
return 0;
}