注:转载请标明出处本博客
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <malloc.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define MAX_NUM 9999
#define MAX 60
typedef char **HuffmanCode;
typedef struct
{
int weight;//权重
int parent,lchild,rchild;
}HTNode,*HuffmanTree;//静态三叉链表中结点的结构定义
typedef struct
{
HuffmanTree HT;
char *c;//指向叶子的指针
int longth;//叶子结点的数目
HuffmanCode HC;//用来存放叶子的哈夫曼编码
}Huffman;//编码的哈夫曼树存储结点结构体定义
void Select(HuffmanTree HT,int end,int *s1,int *s2) //在HT[1]--HT[end]的范围内选择两个parents为零且权值最小的两个结点,序号值给s1,s2返回
{
int i;
int min1=MAX_NUM;//min1,min2标记最小的两个权值
int min2;
for (i=1;i<=end;i++)
{
if ((HT[i].parent==0)&&(HT[i].weight<min1))
{
*s1=i;
min1=HT[i].weight;
}
}
min2=MAX_NUM;
for(i=1;i<=end;i++)
{
if(HT[i].parent==0&&(*s1!=i)&&min2>HT[i].weight)
{
*s2=i;
min2=HT[i].weight;
}
}
}
Huffman HuffmanCoding(Huffman Hfm)//创建哈夫曼树并进行哈夫曼编码
{
int i,n,m,s1,s2,start;
int c,f;
char *cd;
n=Hfm.longth;
if(n<=1) return Hfm;
m=2*n-1;
for(i=n+1;i<=m;++i)
{
Select(Hfm.HT,i-1,&s1,&s2);
Hfm.HT[s1].parent=i;
Hfm.HT[s2].parent=i;
Hfm.HT[i].lchild=s1;
Hfm.HT[i].rchild=s2;
Hfm.HT[i].weight=Hfm.HT[s1].weight+Hfm.HT[s2].weight;
}
Hfm.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=Hfm.HT[i].parent;f!=0;c=f,f=Hfm.HT[f].parent)
{
if(c==Hfm.HT[f].lchild) cd[--start]='0';
else cd[--start]='1';
}
Hfm.HC[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(Hfm.HC[i],&cd[start]);
}
free(cd);
return Hfm;
}
Huffman InputHuffman(Huffman Hfm)//输入哈夫曼树的叶子数目和权重,为建立哈夫曼树做准备
{
int i,n;
printf("\n\n\t\t*****************************************\n");
printf("Please input the number of the chars: ");
scanf("%d",&n);
Hfm.HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));//Hfm.HT为指向HTNode的指针,对之初始化
Hfm.c=(char *)malloc((n+1)*sizeof(char));
for(i=1;i<=n;i++)
{
printf("请输入第%d个叶子字符: ",i);
scanf("%s",&Hfm.c[i]);
printf("请输入它的权重: ");
scanf("%d",&Hfm.HT[i].weight);
Hfm.HT[i].parent=0;
Hfm.HT[i].lchild=0;
Hfm.HT[i].rchild=0;
}
for(;i<=2*n-1;++i)
{
Hfm.HT[i].weight=0;
Hfm.HT[i].parent=0;
Hfm.HT[i].lchild=0;
Hfm.HT[i].rchild=0;
}
Hfm.longth=n;
return Hfm;
}
void Output(Huffman Hfm)//将所有的叶子的哈夫曼编码输出
{
int i,n;
n=Hfm.longth;
printf("\n\n******************输出所有叶子的编码****************\n\n");
for(i=1;i<=n;i++)
{
printf("\n");
printf("Char: %c\t",Hfm.c[i]);
printf("Weight: %d\t",Hfm.HT[i].weight);
printf("Code: ");
puts(Hfm.HC[i]);
}
}
void Encoding(Huffman Hfm)//对报文编码
{
int i=0,j=0,n;
char ch[MAX];
FILE *fp,*ffp;
n=Hfm.longth;
printf("\n\n*******************报文编码**************************\n\n");
if((ffp=fopen("ToBeTran","rt"))==NULL)//
{
printf("\nPlease input the sentence: ");
scanf("%s",&ch);
printf("\n");
fp=fopen("CodeFile","wt+");
}
else
{
fscanf(ffp,"%s",ch);
fclose(ffp);
}
while(ch[j])
{
for(i=1;i<=n;i++)
if(ch[j]==Hfm.c[i])
{
printf("%s",Hfm.HC[i]);
fprintf(fp,"%s",Hfm.HC[i]);
break;
}
j++;
}
rewind(fp);
fclose(fp);
printf("\n报文编码已成功!并已将结果保存到文件CodeFile\n");
}
void Decoding(Huffman Hfm)
{
HuffmanTree p;
int i,n;
int j=0;
char d[50];
char c='a';
FILE *fp;
n=Hfm.longth;
printf("\n\n******************译码************************\n\n");
while(c!='o')
{
printf("\t\ta,从文件'CodeFile'中读取\n\n");
printf("\t\tb,重新输入编码文件\n\n");
printf("\t\to,退出\n\n");
printf("\t\t请选择");
scanf("%s",&c);
switch(c)
{
case 'a':
if((fp=fopen("CodeFile","rt"))==NULL)
printf("文件CodeFile不存在,请先编码");
else
{
fscanf(fp,"%s",d);
fclose(fp);
}
printf("\nThe file is : ");
fp=fopen("TextFile","wt+");
while(d[j])
{
p=&Hfm.HT[2*n-1];
while(p->lchild||p->rchild)
{
if(d[j]=='0')
{ i=p->lchild; p=&Hfm.HT[i]; }
else
{ i=p->rchild; p=&Hfm.HT[i]; }
j++;
}
printf("%c",Hfm.c[i]);
fprintf(fp,"%c",Hfm.c[i]);
}
break;
case 'b':
printf("请输入码文:");
scanf("%s",&d);
printf("\nThe file is : ");
fp=fopen("TextFile","wt+");
while(d[j])
{
p=&Hfm.HT[2*n-1];
while(p->lchild||p->rchild)
{
if(d[j]=='0')
{ i=p->lchild; p=&Hfm.HT[i]; }
else
{ i=p->rchild; p=&Hfm.HT[i]; }
j++;
}
printf("%c",Hfm.c[i]);
fprintf(fp,"%c",Hfm.c[i]);
}
break;
case 'o':break;
}
}
fclose(fp);
printf("\n译码已成功,并已将结果保存到文件'TextFile'中\n");
}
Huffman InitbuildHuffman(Huffman Hfm)
{
int i;
FILE *fp;
fp=fopen("hfmTree","wt");
Hfm=InputHuffman(Hfm);
Hfm=HuffmanCoding(Hfm);
fprintf(fp,"%d\n",Hfm.longth);
for(i=1;i<=Hfm.longth;i++)
fprintf(fp,"%c %d %s ",Hfm.c[i],Hfm.HT[i].weight,Hfm.HC[i]);
rewind(fp);
fclose(fp);
printf("初始化已完毕,哈夫曼树创建成功并已保存到文件'HfmTree中'");
return Hfm;
}
void PrintCoding(Huffman Hfm) //打印文件CodeFile中的内容
{
int i=0;
char *ch;
ch=(char *)malloc(sizeof(char));
FILE *fp,*fpp;
fpp=fopen("CodeFile","rt");
if(fpp==NULL)
{printf("没有文件CodeFile,请先编码!\n");return;}
else
{
fscanf(fpp,"%s",ch);
fclose(fpp);
}
fp=fopen("CodePrin","wt+");
printf("CodeFil文件内容为:");
while(ch[i])
{
printf("%c",ch[i]);i++;
if(i%50==0) printf("\n");
}
fprintf(fp,"%s",ch);
fclose(fp);
printf("已将文件CodeFile中的代码打印完毕\n,并将输出内容保存至文件CodePrin\n");
}
int main()
{ int v;
printf("\t\t欢迎使用哈夫曼码的编/译码系统!\n\n");
for(v=0;v<60;v++)
printf("%c",3);
printf("\t\t\t项目经理--翟周伟\n\n");
printf("\t\t版权所有,盗版必究\n\n");
printf("\t\t在此系统中可以进行以下操作:");
Huffman Hfm;
char choice='a';
while(choice!='f')
{
printf("\n\n\n\t\t*************************************\n\n");
printf("\t\t\ta. 新建初始化哈夫曼树\n\n");
printf("\t\t\tb. 对报文进行哈夫曼树编码\n\n");
printf("\t\t\tc. 报文译码\n\n");
printf("\t\t\td. 输出所有编码\n\n");
printf("\t\t\te. 打印代码文件\n\n");
printf("\t\t\tf. 退出本哈夫曼码的编/译码系统\n\n");
printf("\n\t\t************************************\n");
printf("请选择: ");
scanf("%c",&choice);
switch(choice)
{
case 'a':
Hfm=InitbuildHuffman(Hfm);
printf("\n\n********************Initial*********************\n");
getch(); break;
case 'b':
Encoding(Hfm);
printf("\n\n*******Please enter anykey to continue*******\n");
getch(); break;
case 'c':
Decoding(Hfm);
printf("\n\n*******Please enter anykey to continue********\n");
getch(); break;
case 'd':
Output(Hfm);
printf("\n\n*******Please enter anykey to continue********\n");
getch(); break;
case 'e':
PrintCoding(Hfm);
printf("\n\n*******Please enter anykey to continue********\n");
getch(); break;
case 'f':
printf("感谢你使用本系统,欢迎再次使用!\n");
for(v=0;v<80;v++);
printf("%c",3);
getch();
break;
default:
printf(" Your choice is wrong!\n Please enter anykey to choice again!\n");
getch(); break;
}
}
return 0;
}