构建哈夫曼树及编码

第1关:构建哈夫曼树

任务描述

本关任务:构建哈夫曼树,从键盘读入字符个数n及这n个字符出现的频率即权值,构造带权路径最短的最优二叉树(哈夫曼树)。

测试说明

平台会对你编写的代码进行测试:

输入说明
第一行字符的个数n;
第二行输入这n个字符的权值,即n个整数。

测试输入:
8
5 29 7 8 14 23 3 11

输出说明
第一行输出提示信息;
第二行开始输出插入哈夫曼树元素的值,每个项数据元素的数据项用\t隔开。

预期输出:
哈夫曼树:
HT[1] =5 9 0 0
HT[2] =29 14 0 0
HT[3] =7 10 0 0
HT[4] =8 10 0 0
HT[5] =14 12 0 0
HT[6] =23 13 0 0
HT[7] =3 9 0 0
HT[8] =11 11 0 0
HT[9] =8 11 7 1
HT[10] =15 12 3 4
HT[11] =19 13 9 8
HT[12] =29 14 5 10
HT[13] =42 15 11 6
HT[14] =58 15 2 12
HT[15] =100 0 13 14

代码如下

# include <stdio.h>
# include <iostream>
# include <string.h>
using namespace std;


typedef struct			//define structure HuffmanTree
{   int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef char **  HuffmanCode;

void Select(HuffmanTree HT,int i,int &s1,int &s2) ;//选出HT树到i为止,权值最小且parent为0的2个节点
void HuffmanTreeing(HuffmanTree &HT,int *w,int n);//构建哈夫曼树函数 

void output(HuffmanTree HT,int m);//输出哈夫曼树

int main()            		
{ 
	HuffmanTree HT;
	HuffmanCode HC;
	int n,i;
	int *w;
	scanf("%d",&n);
	w=(int *)malloc(n*sizeof(int));
  	for(i=0;i<n;i++)
	{
		scanf("%d",&w[i]);		
	}
	HuffmanTreeing( HT , w  ,n  );	
	cout<<"哈夫曼树:"<<endl;
	output(HT,2*n-1);	
	return 0;
}

void Select(HuffmanTree HT,int i,int &s1,int &s2)  
{ 	//选出HT树到i为止,权值最小且parent为0的2个节点
	//s1 is the least of HT[].weight
	//s2 is the second least of HT[].weight
	/********** Begin **********/ 
	int t,m=0x3f3f3f3f,n=0x3f3f3f3f;
	for(t=1;t<=i;t++){
		if(HT[t].weight<m && HT[t].parent==0){
			m=HT[t].weight;
			s1=t;
		}
	}
	int temp=HT[s1].weight;
	HT[s1].weight=0x3f3f3f3f;
	for(t=1;t<=i;t++){
		if(HT[t].weight<n && HT[t].parent==0){
			n=HT[t].weight;
			s2=t;
		}
	}
	HT[s1].weight=temp;
	/********** End **********/
} 


void HuffmanTreeing(HuffmanTree &HT,int *w,int n) //构建哈夫曼树函数
{ // w存放n个字符的权值(均>0),构造赫夫曼树HT
	/********** Begin **********/
	int i,m,s1,s2;
	HuffmanTree p;
	if(n<=1) return;
	m=2*n-1;
	HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
	for(p=HT+1,i=1;i<=n;++i,++p,++w){
		p->weight=*w;
		p->parent=0;
		p->lchild=0;
		p->rchild=0;
	}
	for(i=n+1;i<=m;++i,++p){
		p->weight=0;
		p->parent=0;
		p->lchild=0;
		p->rchild=0;
	}
	for(i=n+1;i<=m;++i){
		Select(HT,i-1,s1,s2);
		HT[s1].parent=i;
		HT[s2].parent=i;
		HT[i].lchild=s1;
		HT[i].rchild=s2;
		HT[i].weight=HT[s1].weight+HT[s2].weight;
	}
	/********** End **********/
}   


void output(HuffmanTree HT,int m)
{ //输出哈夫曼树
	for(int i=1;i<=m;++i)
	{   
		cout<<"HT["<<i<<"] ="<<HT[i].weight<<"\t"<<HT[i]. parent<<"\t";
		cout<<"\t" <<HT[i]. lchild <<"\t" <<HT[i]. rchild<<endl;
	}
}

第2关:根据哈夫曼树构建哈夫曼编码

任务描述

本关任务:根据构建好的哈夫曼树,创建一张哈夫曼编码表,输出每个字符的哈夫曼编码。

测试说明

平台会对你编写的代码进行测试:

测试输入:
8
5 29 7 8 14 23 3 11

预期输出:
哈夫曼编码:
HT[1] node’s Huffman code is: 0001
HT[2] node’s Huffman code is: 10
HT[3] node’s Huffman code is: 1110
HT[4] node’s Huffman code is: 1111
HT[5] node’s Huffman code is: 110
HT[6] node’s Huffman code is: 01
HT[7] node’s Huffman code is: 0000
HT[8] node’s Huffman code is: 001

代码如下

# include <stdio.h>
# include <iostream>
# include <string.h>
using namespace std;


typedef struct			//define structure HuffmanTree
{   int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef char **  HuffmanCode;

void Select(HuffmanTree HT,int i,int &s1,int &s2) ;//选出HT树到i为止,权值最小且parent为0的2个节点
void HuffmanTreeing(HuffmanTree &HT,int *w,int n);//构建哈夫曼树函数 
void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n); //建立哈夫曼树编码
void output(HuffmanTree HT,int m);//输出哈夫曼树

int main()            		
{ 
	HuffmanTree HT;
	HuffmanCode HC;
	int n,i;
	int *w;
	scanf("%d",&n);
	w=(int *)malloc(n*sizeof(int));
  	for(i=0;i<n;i++)
	{
		scanf("%d",&w[i]);		
	}
	HuffmanTreeing( HT , w  ,n  );	
	HuffmanCoding( HT,  HC ,n   );	
	cout<<"哈夫曼编码:"<<endl;
	for(i=1;i<=n;i++)
    {
		printf("HT[%d] node's Huffman code is: %s\n",i,HC[i]);
	}	
	return 0;
}

void Select(HuffmanTree HT,int i,int &s1,int &s2)  
{ 	//选出HT树到i为止,权值最小且parent为0的2个节点
	//s1 is the least of HT[].weight
	//s2 is the second least of HT[].weight
	int j,k=1;                	
	while(HT[k].parent!=0)	   
		k++;
	s1=k;
	for(j=1;  j<=i  ;++j)
		if(HT[j].parent==0 &&   HT[j].weight <  HT[s1].weight     )
			s1=j;
	k=1;
	while( HT[k].parent!=0||  k==s1   ) 
		k++;
	s2=k;
	for(j=1;j<=i;++j)
		if(   HT[j].parent==0   && HT[j].weight<HT[s2].weight && j!=s1)
			s2=j;

} 


void HuffmanTreeing(HuffmanTree &HT,int *w,int n) //构建哈夫曼树函数
{ // w存放n个字符的权值(均>0),构造赫夫曼树HT
	int m,i,s1,s2,start,c,f;
	HuffmanTree p;
	if(n<=1)
		return;
	m= 2*n-1 ;
	HT=(HuffmanTree) malloc( (m+1)*sizeof(   HTNode     ) );
	for(p=HT+1,i=1;i<=n;++i,++p)	//initial HT[1...n]
	{ 
		p->weight=  w[i-1] ;
        p->parent=0;
        p->lchild=0;
        p->rchild=0;
	}
	for(  ;i<=m;++i,++p)			//initial HT[n+1...2*n1]
	{
        p->weight= 0;  
        p->parent=0;
        p->lchild=0;
        p->rchild=0;
	}
	for(i=n+1;i<=m;++i)
	{  
		Select(HT,i-1,s1,s2);	// 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2
        HT[s1].parent= i ;
        HT[s2].parent= i ;
        HT[i].lchild= s1 ;
        HT[i].rchild= s2 ;
        HT[i].weight= HT[s1].weight+HT[s2].weight ;
	}	

}   


void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n) //建立哈夫曼树编码
{ 	// 根据赫夫曼树HT,求出n个字符的赫夫曼编码HC
	/********** Begin **********/
	char *cd;
	int i,start;
	unsigned c,f;
	HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
	cd=(char*)malloc(n*sizeof(char));
	cd[n-1]='\0';
	for(i=1;i<=n;i++){
		start=n-1;
		for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
			if(HT[f].lchild==c)
				cd[--start]='0';
			else
				cd[--start]='1';
		HC[i]=(char*)malloc((n-start)*sizeof(char));
		strcpy(HC[i],&cd[start]);
	}
	free(cd);
	/********** End **********/ 
} 

void output(HuffmanTree HT,int m)
{ //输出哈夫曼树
	for(int i=1;i<=m;++i)
	{   
		cout<<"HT["<<i<<"] ="<<HT[i].weight<<"\t"<<HT[i]. parent<<"\t";
		cout<<"\t" <<HT[i]. lchild <<"\t" <<HT[i]. rchild<<endl;
	}
}
  • 18
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值