题目描述
假设某通信报文的字符集由A,B,C,D,E,F这6个字符组成,它们在报文中出现的频度(频度均为整数值)。
(1)构造一棵哈弗曼树,依次给出各字符编码结果。
(2)给字符串进行编码。
(3)给编码串进行译码。
规定:
构建哈弗曼树时:左子树根结点权值小于等于右子树根结点权值。
生成编码时:左分支标0,右分支标1。
输入
第一行:依次输入6个整数,依次代表A,B,C,D,E,F的频度,用空格隔开。
第二行:待编码的字符串
第三行:待译码的编码串
输出
前6行依次输出各个字符及其对应编码,格式为【字符:编码】(冒号均为英文符号)
第7行:编码串
第8行:译码串
样例输入 Copy
3 4 10 8 6 5
BEE
0010000100111101
样例输出 Copy
A:000
B:001
C:10
D:01
E:111
F:110
001111111
BADBED
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct hafutree
{
char ch;
int parent;
int weight;
int lchild;
int rchild;
}hafutree;
///初始化哈夫曼树
hafutree **inithafutree(int wet[])
{
hafutree **head;
char a='A';
head=(hafutree **)malloc(sizeof(hafutree *)*12);
for(int i=1;i<=6;i++,a++)
{
head[i]=(hafutree *)malloc(sizeof(hafutree));
head[i]->ch=a;
head[i]->weight=wet[i-1];
head[i]->parent=0;
head[i]->lchild=0;
head[i]->rchild=0;
}
for(int i=7;i<12;i++)
{
head[i]=(hafutree *)malloc(sizeof(hafutree));
head[i]->ch='#';
head[i]->weight=0;
head[i]->parent=0;
head[i]->lchild=0;
head[i]->rchild=0;
}
return head;
}
///创建好哈夫曼树
void create_hafutree(hafutree **head)
{
int m,n;//m第一个最小,n第二个最小
int k=6;//记录下一次比较位置
while(k<11)
{
for(int j=1;j<=k;j++)
{
if(head[j]->parent==0)
{
m=j;
break;
}
}
for(int i=1;i<=k;i++)
{
if(head[m]->weight>=head[i]->weight&&head[i]->parent==0)
{
m=i;
}
}
for(int j=1;j<=k;j++)
{
if(head[j]->parent==0&&m!=j)
{
n=j;
break;
}
}
for(int i=1;i<=k;i++)
{
if(i==m)
{
continue;
}
if(head[n]->weight>=head[i]->weight&&head[i]->parent==0)
{
n=i;
}
}
head[++k]->weight=head[m]->weight+head[n]->weight;
head[k]->lchild=m;
head[k]->rchild=n;
head[m]->parent=k;
head[n]->parent=k;
}
/*getchar();
printf("完成哈夫曼树\n");
for(int i=1;i<12;i++)
{
//printf("%d",head[i]->weight);
printf("%d-节点值%c-",i,head[i]->ch);
printf("父亲%d-",head[i]->parent);
printf("左孩子%d-",head[i]->lchild);
printf("右孩子%d-\n",head[i]->rchild);
}
getchar();*/
}
进行哈夫曼编码
void makecode(hafutree **head,char **ch)
{
char a[6];
int start;
int p;
int k;
for(int i=1;i<=6;i++)
{
start=5;
a[start]='\0';
p=head[i]->parent;//p表示双亲
k=i;//k记录顺序
while(p)
{
if(head[p]->lchild==k)
{
a[--start]='0';
}
else if(head[p]->rchild==k)
{
a[--start]='1';
}
k=p;//k记录找到孩子的双亲
p=head[p]->parent;
}
ch[i]=(char *)malloc(sizeof(char)*(6-start));
strcpy(ch[i],&a[start]);
}
return ;
}
///进行哈夫曼译码
char *translatecode(hafutree **head,char hafu_number[])
{
int k=0;//记录边缘后位置
int m,x,n;
char *tr;
tr=(char *)malloc(sizeof(char)*20);
x=0;
for(int i=k;hafu_number[i]!='\0';)
{
m=11;
n=i;
while(head[m]->lchild&&head[m]->rchild)
{
if(hafu_number[n]=='0')
{
m=head[m]->lchild;
}
else if(hafu_number[n]=='1')
{
m=head[m]->rchild;
}
n++;
i++;
}
tr[x++]=head[m]->ch;
tr[x]='\0';
}
return tr;
}
int main()
{
char hafuch[20];//待编译码
char hafu_number[30];//待解译码
char hafuch_num[30]="";
hafutree **head;
int wet[6];//权值
int j;
char *tr;
tr=(char *)malloc(sizeof(char)*20);
for(int i=0;i<6;i++)
{
scanf("%d",&wet[i]);
}
getchar();
gets(hafuch);
gets(hafu_number);
head=inithafutree(wet);
create_hafutree(head);
char **ch;
ch=(char **)malloc(sizeof(char *)*7);
makecode(head,ch);
for(int i=0;hafuch[i]!='\0';i++)
{
j=1;
while(j<=6)
{
if(head[j]->ch==hafuch[i])
{
strcat(hafuch_num,ch[j]);
break;
}
j++;
}
}
for(int i=1;i<=6;i++)
{
printf("%c:%s\n",head[i]->ch,ch[i]);
}
puts(hafuch_num);
tr=translatecode(head,hafu_number);
puts(tr);
}