<span style="color:#6600cc;">#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct{
char a;//记录对应字符
int weight;//权值
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char * *HuffmanCode;//动态分配数组存储哈夫曼编码表
void Select(HuffmanTree HT,int m,int *s1)//选择双亲节点为0且权值最小的节点
{int i,j,k,h,a,b;
for(a=1;a<=m;a++)
if(HT[a].parent==0)
break;
i=a;k=a;
for(;i<=m;i++)
if(HT[i].weight<HT[k].weight&&HT[i].parent==0)
k=i;
*s1=k;
}
//求哈夫曼编码
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,char *s,int n)
{
int m,i,start,s1,s2,c,f;
char *cd;
HuffmanTree p;
if(n<=1) return;
m=2*n-1;
*HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1;i<=n;i++,w++,s++)
{(*HT)[i].weight=*w;//叶子节点的权值不变
(*HT)[i].a=*s;
(*HT)[i].parent=0,(*HT)[i].lchild=0,(*HT)[i].rchild=0;}
for(i=n+1;i<=m;i++)
(*HT)[i].parent=0;//parent初始化
for(i=n+1;i<=m;++i){//建哈夫曼树
Select(*HT,i-1,&s1);(*HT)[s1].parent=i;
Select(*HT,i-1,&s2);/*选择parent为0且权值最小的两个节
点分别作为s1和s2*/
(*HT)[s2].parent=i;
(*HT)[i].lchild=s1;(*HT)[i].rchild=s2;(*HT)[i].a='0';
(*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;
}
//从叶子到根逆向求每个字符的哈夫曼编码
(*HC)=(HuffmanCode)malloc((n+1)*sizeof(char *));/*分配n个
字符编码的头指针向量*/
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));/*为第i
个字符编码分配空间*/
strcpy((*HC)[i],&cd[start]);//从cd复制编码到HC
}
}
//解码
void HUffmanDising(HuffmanTree HT,int n){
FILE *fp3,*fp4;HuffmanTree p;
int c,m;char b;
p=HT;m=2*n-1;*p=HT[m];
fp3=fopen("File3.txt","r");
fp4=fopen("File4.txt","w");
if(fp3!=NULL)
{fscanf(fp3,"%c",&b);/*读入一个字符,如果为‘0’遍历左子树,
为‘1’遍历右子树,遇到叶子节点输出*/
while(!feof(fp3)){
if(b=='0'){
if((*p).a=='0')
c=(*p).lchild,(*p)=HT[c];//指向左孩子
}
if(b=='1'){
if((*p).a=='0')
c=(*p).rchild,(*p)=HT[c];//指向右孩子
}
if((*p).a!='0') fprintf(fp4,"%c",(*p).a),//叶子节点输出
(*p)=HT[m];//指向根结点
if(!feof(fp3)) fscanf(fp3,"%c",&b);
}
}
fclose(fp4);fclose(fp3);
}
void PrintfBitree(HuffmanTree *HT,HuffmanCode *HC,int n)
{int i,j=1,m=n*2-1;
printf("序号 字符 权值 双亲 左孩子 右孩子 哈夫曼码\n");
for(i=1;i<=m;i++,j++)
{printf(" %02d %c %2d %2d %2d %2d",i,(*HT)[i].a,(*HT)[i].weight,(*HT)[i].parent,(*HT)[i].lchild,(*HT)[i].rchild);
if(j<=n) printf(" %s ",(*HC)[j]);
printf("\n");}
}
int main()
{ int a[258],n,c[100],i,j,k,z;char e;char m[100],b;
HuffmanTree HT;HuffmanCode HC;
FILE *fp1,*fp2,*fp3,*fp4;
for(i=0;i<=256;i++)
a[i]=0;//读入一个字符,在数组a中的位置由其ASCII吗决定
for(i=0;i<100;i++)
c[i]=0;//记录每一个字符的权值
fp1=fopen("File1.txt","r");
if(fp1!=NULL)
{
while(!feof(fp1)){
fscanf(fp1,"%c",&e);
if(!feof(fp1)) a[(int)e]++;//统计出现次数
}
}
fclose(fp1);
for(i=0,j=0;i<=256;i++)
if(a[i]!=0)
c[j++]=a[i],m[j-1]=(char)i;//将字符存到数组m中
HuffmanCoding(&HT,&HC,c,m,j);
fp1=fopen("File1.txt","r");
fp2=fopen("File2.txt","w");
fp3=fopen("File3.txt","w+");
if(fp1!=NULL)//在文件二语三中输出文件一中内容所对应的哈夫曼吗
{
while(!feof(fp1)){
fscanf(fp1,"%c",&e);
if(feof(fp1)) break;
for(i=0;i<j;i++)
if(m[i]==e) break;
fprintf(fp2,"%s",HC[i+1]);
fprintf(fp3,"%s",HC[i+1]);
}
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
PrintfBitree(&HT,&HC,j);//输出相关信息
HUffmanDising(HT,j);//解码函数
}
</span>