构造这种树的算法最早由哈夫曼于1952年提出的,因此称之为哈夫曼树。
什么是哈夫曼树(Huffman Tree)+概念
(1)带权路径长度(WPL):设二叉树有n个叶子结点,每个叶子结点带 有权值 wk,从根结点到每个叶子结点的长度为 Lk,则每个叶子结 点的带权路径长度之和就是:WPL=w1L1+w2L2+…+wn*Ln。 最优二叉树或哈夫曼树: WPL最小的二叉树 。
(2)结点的权:在许多的应用中,将树中的结点赋予一个有着实际意义的数值,称此数值为该结点的权。
(3)结点的带权路径长度:从根结点到某个结点的路径长度与该结点所带的权值的乘积为该结点的带权路径长度。
构造一棵哈夫曼树
根据哈夫曼树的定义,一棵二叉树要使其WPL值最小,必须使权值越大的叶子节点越靠近根节点,而权值越小的叶子节点越远离根节点。那么如何构造一棵哈夫曼树呢?其方法如下:
(1)给定的n个权值{W1,W2,…,Wn}构造n棵只有一个叶子节点的二叉树,从而得到一个二叉树的集合F={T1,T2,…,Tn};
(2)在F中选取根节点的权值最小和次小的两棵二叉树作为左、右子树构造一棵新的二叉树,这棵新的二叉树根节点的权值为其左、右子树根节点权值之和;
(3)在集合F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到集合F中;
(4)重复(2)、(3)两步,当F中只剩下一棵二叉树时,这棵二叉树便是所要建立的哈夫曼树。
注:每次把权值最小的两棵二叉树合并
*做题试试:*W={ 0.05, 0.29, 0.07, 0.08, 0.14, 0.23,0.03, 0.11}
构造一棵哈夫曼树的算法
其算法思路是:
1.n个叶子结点只有data和weight域值,先将所有2n-1个结点的parent、lchild和rchild域置为初值0。
2.处理每个非叶子结点ht[i](存放在ht[n+1]~ht[2n-1]中):从ht[1] ~ht[i-1]中找出根结点(即其parent域为0)最小的两个结点ht[lnode]和ht[rnode],将它们作为ht[i]的左右子树,ht[lnode]和ht[rnode]的双亲结点置为ht[i],并且ht[i].weight= ht[lnode].weight+ht[rnode].weight。
3.如此这样直到所有n-1个非叶子结点处理完毕。
用ht[]数组存放哈夫曼树,对于具有n个叶子结点的哈夫曼树,总共有2n-1个结点。
typedef struct /*哈夫曼树结点的结构*/
{
char data; /*数据用字符表示*/
int weight; /*权值*/
int parent; /*双亲*/
int leftchild; /*左孩子*/
int rightchild; /*右孩子*/
}HuffNode;
int HuffmanCreate(HuffNode *ht)
{
int i,k,n,min1,min2,lnode,rnode;
printf("请输入元素个数:");
scanf("%d",&n);
for(i=1;i<=n;i++)
/* 输入结点值和信息 */
{
getchar()