哈夫曼树的原理结论
- 带权路径长度WPL最小的二叉树(WPL:从根到某点的长度与该点的权值相乘的所有点的和)
- 哈夫曼树的节点数=2*叶子数-1(叶子数就是你输入的点数)
哈夫曼树的构造方式
- 从叶子选择权值最小的两个点组成一个节点
- 将组合的这两个节点的父亲节点指向你组成的这个节点
- 将你组成的节点的左右儿子节点指向这两个点(小的在左 大的在右)
- 将该节点的权值加入叶子中
- 重复1
哈夫曼编码
- 从根节点开始到该点的距离就代表你编码的长度
- 左儿子的编码单元是0 右儿子的编码单元是1
- 从根节点到该点的所有点的编码组合起来就是该点的编码
接下来 就是代码时间了
哈夫曼树的构造
- 我们首先来看看树的结构体是啥样的:
typedef struct node
{
char data;//存储叶子的名字
int weight; //存储权值
int parent; //存储父亲节点
int lchild,rchild;//存储左右儿子节点
int longs;//存储根到该节点的距离
char m;//存储该点的一个编码
}Node;
typedef struct tree
{
node *elem;
int leaf;//存储叶子的个数
}Tree;
- 我们肯定得初始化吧:
void init(tree &HT)//初始化
{
cout<<"输入叶子个数 :"<<endl;
cin>>HT.leaf;
HT.elem=(node *)malloc((2*HT.leaf)*sizeof(node));//分配空间
cout<<"输入名称:"<<endl;
for(int i=1;i<=HT.leaf;i++)
{
cin>>HT.elem[i].data;
}
cout<<"输入权重:"<<endl;
for(int i=1;i<=HT.leaf;i++)
{
cin>>HT.elem[i].weight;
}
for(int i=1;i<=2*HT.leaf-1;i++)
{
HT.elem[i].parent=HT.elem[i].lchild=HT.elem[i].rchild=HT.elem[i].longs=0;//初始化
if(i>=HT.leaf+1)
{
HT.elem[i].data=HT.elem[i].weight='\0';
}
}
}
- 终于开始构造哈夫曼树,首先我们要先找到最小的两个点:
if(HT.elem[i].weight<min1)//比较过程
{
min2=min1;//min1 min2 是很大的数 方便第一次找最小值
m2=m1;//m1 m2 是记录这两个最小点的序号 方便后面的指向
min1=HT.elem[i].weight;
m1=i;
}
else if(HT.elem[i].weight<min2)
{
min2=HT.elem[i].weight;
m2=i;
}
然后 我们得做什么 对 我们要把这两个点组合 并且将他们的指向完成(注意 我这里的写法是为了方便待会做编码 才有的m 所以可以忽略):
HT.elem[k].weight=min