哈弗曼树也称为最优二叉树,它是带权路径长度最短的树,权值越大的结点就离根节点越近。(一般在哈弗曼编码中,权值表示出现的概率,即出现的概率越大,那么访问时的路径就越短)。
构建哈弗曼树:
将n个权值构造出n棵只有根节点的树,构成森林。
在森林中选出两个根结点的权值最小的树分别做左右孩子合并一棵新树,且新树的根结点权值为左右结点之和。
从森林中删除选取的两棵树,并将构成的新想树插入到森林中。
构建哈弗曼树的步骤图解如下。
代码实现:
//哈弗曼树
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node* lchild;
struct Node* rchild;
}Node;
//创建树
Node* create_tree(int *a,int n)
{
Node* root=NULL;
//创建动态数组
Node** node_a=(Node**)malloc(n*sizeof(Node*));
int i,j;
for(i=0;i<n;i++)
{
node_a[i]=(Node*)malloc(1*sizeof(Node));
node_a[i]->data=a[i];
node_a[i]->lchild=NULL;
node_a[i]->rchild=NULL;
}
int min1,min2;
//寻找最小两个数
for(i=1;i<n;i++)
{
min1=-1;
for(j=0;j<n;j++)
{
if(node_a[j]!=NULL && min1==-1)
{
min1=j;
continue;
}
if(node_a[j]!=NULL)
{
min2=j;
break;
}
}
//开始寻找最小两个数的下标
for(j=min2;j<n;j++)
{
if(node_a[j]!=NULL)
{
if(node_a[j]->data < node_a[min1]->data)
{
min2=min1;
min1=j;
continue;
}
if(node_a[j]->data < node_a[min2]->data)
{
min2=j;
}
}
}
//构建成新树
root=(Node*)malloc(1*sizeof(Node));
root->data=node_a[min1]->data + node_a[min2]->data;
printf("data:%d\n",root->data);
root->lchild=node_a[min1];
root->rchild=node_a[min2];
//将原来两棵树从森林中去掉,并添加新树
node_a[min1]=root;
node_a[min2]=NULL;
}
free(node_a);
node_a=NULL;
return root;
}
//输出树
void print_tree(Node* root)
{
if(root==NULL)
return ;
printf("%d\t",root->data);
print_tree(root->lchild);
print_tree(root->rchild);
}
int main(int argc, char const *argv[])
{
int data[]={6,1,7,2,5};
Node*root=create_tree(data,5);
print_tree(root);
printf("\n");
return 0;
}说明:以上代码只是根据数据构建一棵哈弗曼树,并没有进行其他操作,没有实现具体应用,如哈弗曼编码与解码。
本文出自 “君峰俊宇” 博客,请务必保留此出处http://10274409.blog.51cto.com/10264409/1825889
原文:http://10274409.blog.51cto.com/10264409/1825889