您的位置:首页 > 其它

哈夫曼树以及哈夫曼编码的创建

2016-01-19 10:21 309 查看
#include<stdio.h>
#include<string.h>
#define Maxvalue 20
#define Maxleaf 15
#define Maxnode (2*Maxleaf-1)
int n=0,len,j,m;
typedef struct
{
	int num;         //存放字母的种类
	char ch;         //存放字母的个数
}inf;
inf info[Maxleaf];    //定义此类型数组
typedef struct
{
	int weight;     //权值
	int parent;     //双亲
	int lchild;     //左孩子
	int rchild;     //右孩子
}HTnode;
HTnode Hofftree[Maxnode];   //定义此类型数组
typedef struct
{    
	char cd[10];            //存储每个结点的哈夫曼编码
	int start;               //起始位置
}Hcode;
Hcode hcd[Maxleaf];         //定义此类型数组
void Count()                //统计字符串中字母总个数以及各个字母的个数                     
{   
    int k,i;
    char s[Maxvalue];
	printf("请输入字符串:\n");
	scanf("%s",&s);
	len=strlen(s);
	printf("字符串字母的个数为:%d\n",len);
	info[0].ch=s[0];
	info[0].num=1;
    for(k=1;k<=len;k++)
	{
		for(m=0;m<=n;m++)                 //s[k]与s[m]是同一个字母num加1
			if(info[m].ch==s[k])
			{
				++info[m].num;
				break;
			}
			if(m>n)                     //有新的字母s[k]出现
			{
				info[++n].ch=s[k];
				info
.num=1;
			}
				
	}
	for(j=0;j<n;j++)
	{
		printf("字符%c的个数为:%d\n",info[j].ch,info[j].num);
	}
	for(i=0;i<n;i++)                   //将字母的权值赋予节点
   Hofftree[i].weight=info[i].num;
}
void CreatHT(HTnode Hofftree[])       //构造哈夫曼树
{
   int i,p,lnode,rnode,k;
   double min1,min2;
   for(i=0;i<=2*n-1;i++)               //所有结点相关域置初值-1
Hofftree[i].parent=Hofftree[i].lchild=Hofftree[i].rchild=-1;
   for(i=n;i<2*n-1;i++)                //构造哈夫曼树
   {
	   min1=min2=32767;
	   lnode=rnode=-1;                 //lnode和rnode为最小权值的两个结点的位置              
	   for(k=0;k<=i-1;k++)
		   if(Hofftree[k].parent==-1)   //Hofftree[]中找权值最小的两个结点
		   {
			   if(Hofftree[k].weight<min1) //只在尚未构造二叉树的节点中查找
			   {
				   min2=min1;
				   rnode=lnode;
				   min1=Hofftree[k].weight;
				   lnode=k;
			   }
			   else if(Hofftree[k].weight<min2)
			   {
				   min2=Hofftree[k].weight;
				   rnode=k;
			   }
		   }
		   Hofftree[i].weight=Hofftree[lnode].weight+Hofftree[rnode].weight;
		   Hofftree[i].lchild=lnode;        //Hofftree[i]作为双亲结点
		   Hofftree[i].rchild=rnode;
		   Hofftree[lnode].parent=i;
		   Hofftree[rnode].parent=i;
		   
   }
}
void printHT(HTnode Hofftree[])           //打印哈夫曼树
{   int i;
	printf("哈夫曼树:\n");
	printf("weight  lchild  rchild  parent\n");
	for(i=0;i<2*n-1;i++)
		
    printf("%d\t%d\t%d\t%d\n",Hofftree[i].weight,Hofftree[i].lchild,Hofftree[i].rchild,Hofftree[i].parent);  
}
void Creathcode(HTnode Hofftree[],Hcode hcd[])  //求哈夫曼编码
{
	int i,f,c,j;
	Hcode hc;
	for(i=0;i<n;i++)
	{
		hc.start=n;
		c=i;
		f=Hofftree[i].parent;
		while(f!=-1)                           //循环直到根节点
		{
			if(Hofftree[f].lchild==c)          //当前节点是双亲结点的左孩子结点
				hc.cd[hc.start--]='0';
		    else
				hc.cd[hc.start--]='1';         //当前节点是双亲结点的右孩子结点
			c=f;                               //再对双亲结点做同样的操作
		    hcd[i]=hc;
			f=Hofftree[f].parent;              //start指向哈夫曼编码的最开始字符
		}
		hc.start++;                           
		hcd[i]=hc;
	} 
	    for(i=0;i<n;i++)
	   { 
        printf("%c的编码为\n",info[i].ch);
		for(j=hcd[i].start;j<=n;j++)
        printf("%c",hcd[i].cd[j]);
        printf("\n");	
	   }
	
}

int main()
{   
	Count();                                 //统计所输入字符串中字母总个数以及各个字母的个数
	CreatHT(Hofftree);                       //构造哈夫曼树
	printHT(Hofftree);                       //打印哈夫曼树
	Creathcode(Hofftree,hcd);                //求哈夫曼编码
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: