Description
写一个哈夫曼码的编/译码系统,要求能对要传输的报文进行编码和解码。构造哈夫曼树时,权值小的放左子树,权值大的放右子树,编码时右子树编码为1,左子树编码为0。
Input
输入表示字符集大小为n(n<=100)的正整数,以及n个字符和n个权值(正整数,值越大表示该字符出现的概率越大);输入串长小于或等于100的目标报文。
Output
经过编码后的二进制码,占一行;
以及对应解码后的报文,占一行;
最后输出一个回车符;
Sample Input 5 a b c d e 12 40 15 8 25
bbbaddeccbbb
Sample Output 00011111110111010110110000
bbbaddeccbbb
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxval 10000
typedef struct
{
char ch;//标签
int weight;
int parent,lchild,rchild;
}tree;//变量名
typedef struct
{
char bit[100];//位串
int start;//编码在位串中的起始位置
}codetype;//变量名
tree ht[1005];
codetype co[200];//存放各叶子节点的编码的数组
int p=0;
char str[1000]={'\0'};
void creat(tree ht[],int n)//创建哈夫曼树
{
int i,j,p1,p2;//p1,p2分别记住每次合并时权值最小和次小的两个根节点的下标
int small1,small2;
for(i=0;i<2*n-1;i++)
{
ht[i].parent=-1;
ht[i].lchild=-1;
ht[i].rchild=-1;
ht[i].weight=0;
ht[i].ch=-1;
}
for(i = 0; i < n; i++)
{
scanf(" ");//空格符
scanf("%c",&ht[i].ch);
}
scanf(" ");//空格符
for(i=0;i<n;i++)
{
scanf("%d ",&ht[i].weight);
}
for(i=n;i<2*n-1;i++)
{
p1=0;p2=0;
small1=maxval;
small2=maxval;
for(j=0;j<i;j++)//从i个数字中选择最小的p1和次小的p2
{
if(ht[j].parent==-1)
{
if(ht[j].weight<small1)
{
small2=small1;
small1=ht[j].weight;
p2=p1;
p1=j;
}
else if(ht[j].weight<small2)
{
small2=ht[j].weight;
p2=j;
}
}
}
ht[p1].parent=i;
ht[p2].parent=i;
ht[i].lchild=p1;
ht[i].rchild=p2;
ht[i].weight=ht[p1].weight+ht[p2].weight;
}
}
void bianma(codetype co[],int n)//编码
{ //从叶子结点出发向上回溯
int i,j;
codetype cd;//缓冲变量
for(i = 0; i < n; i ++)
{
cd.start = n-1;
int cur = i;
int p = ht[cur].parent;
while(p!=-1)//存在双亲时
{
if(ht[p].lchild == cur)
cd.bit[cd.start] = '0';//左子树生成0
else
cd.bit[cd.start] = '1';//右子树生成1
cd.start--;
cur = p;
p = ht[cur].parent;
}
for(j = cd.start+1; j<n; j++)
co[i].bit[j] = cd.bit[j];
co[i].start = cd.start;//将各个叶子结点的哈夫曼编码存在co数组之中并保存编码在位串中的起始位置
}
}
void jiema(char str[], tree ht[], int n)//解码
{
int num = 2*n-1;//结点个数
int i =0;
int t;
int k;
k=strlen(str);
while(i<k)
{
t = num-1;//根节点下标
while((ht[t].lchild!=-1)&&(ht[t].rchild!=-1))
{
if(str[i] == '0')
t = ht[t].lchild;
else
t = ht[t].rchild;
i++;
}
printf("%c", ht[t].ch);
}
}
void output(int n)//输出编码
{
char st[1000];
int i,j,k,q;
scanf("%s",st);
q=strlen(st);
for(i = 0;i<q; i++)
{
for(j =0;j<n; j++)
{
if(st[i] == ht[j].ch)
{
for(k = co[j].start+1; k < n; k++)
{
printf("%c", co[j].bit[k]);
str[p]=co[j].bit[k];//将编码保存在数组中以便译码时使用
p++;
}
}
}
}
printf("\n");
}
int main()
{
int n;
scanf("%d",&n);
creat(ht,n);
bianma(co,n);
output(n);
jiema(str,ht,n);
return 0;
}