哈弗曼编码大家一定很熟悉吧(不熟悉也没关系,自己查去。。。)。现在给你一串字符以及它们所对应的权值,让你构造哈弗曼树,从而确定每个字符的哈弗曼编码。当然,这里有一些小规定:
1.规定哈弗曼树的左子树编码为0,右子树编码为1;
2.若两个字符权值相同,则ASCII码值小的字符为左孩子,大的为右孩子;
3.创建的新节点所代表的字符与它的左孩子的字符相同;
4.所有字符为ASCII码表上32-96之间的字符(即“ ”到“`”之间的字符)。
3 a 10 b 5 c 8 4 a 1 b 1 c 1 d 1
a:0 b:10 c:11 a:00 b:01 c:10 d:11
#include
#include
#include
#define N 30
#define M 2*N-1
typedef struct {
int weight;
int parent;
int lchild;
int rchild;
}HTnode,HTree[M+1];
typedef struct zi{
char n;//定义结构类型
}zi;
zi ch[55];
typedef char* HaCode[N+1];
void select(HTree ht,int n,int *p,int *q){
int min1=32767,min2=32767,t,i;
for(i=1;i<=n;i++)
if(ht[i].parent==0)
{
if(min1>ht[i].weight){
min1=ht[i].weight;
*p=i;
}
}
for(i=1;i<=n;i++)
if(ht[i].parent==0&&i!=*p)
{
if(min2>ht[i].weight&&i!=*p){//select函数
min2=ht[i].weight;
*q=i;
}
}
if(ht[*p].weight==ht[*q].weight&&ch[*p].n>ch[*q].n){
t=*q;
*q=*p;
*p=t;
}
}
void CrtHTree(HTree ht,int n){//建树
int i;
int s1,s2,m=2*n-1;
for(i=1;i<=n;i++){
scanf("\n%c%d",&ch[i].n,&ht[i].weight);
ht[i].parent=ht[i].lchild=ht[i].rchild=0;
}
for(i=n+1;i<=m;i++)
ht[i].weight=ht[i].parent=ht[i].lchild=ht[i].rchild=0;
for(i=n+1;i<=m;i++)
{
select(ht,i-1,&s1,&s2);
ht[i].weight=ht[s1].weight+ht[s2].weight;
ht[s1].parent=i;ht[s2].parent=i;
ht[i].lchild=s1;ht[i].rchild=s2;
}
}
void CrtHacode(HTree ht,HaCode hc,int n){//编码
char *cd;
int start,c,i,p;
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++){
start=n-1;
c=i;p=ht[i].parent;
while(p!=0){
--start;
if(ht[p].lchild==c)
cd[start]='0';
else
cd[start]='1';
c=p;p=ht[p].parent;
}
hc[i]=(char*)malloc(sizeof(char));
strcpy(hc[i],&cd[start]);
}
free(cd);
}
int main(){
int l,i;
HaCode hc;
HTree ht;
while(~scanf("%d",&l)){//主函数
CrtHTree(ht,l);
CrtHacode(ht,hc,l);
for(i=1;i<=l;i++)
printf("%c:%s\n",ch[i].n,hc[i]);
}
return 0;
}
//可能是指针或数组方面的用错了,测试数据没有问题,就是报错,可能是、。。。。。