#include
#include
#include
#include
#include
#include
typedef struct
{
int weight;
int parent,lchild,rchild;
}HTNode,* HuffmanTree;//哈夫曼结构
typedef char **HuffmanCode;//哈夫曼编码
HuffmanTree HT;
HuffmanCode HC;
int *w,i=0,j=0,n=0,number=0;
char *z;
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)//W存放N个字符的权值,构造哈夫曼树HT,并求出N个字符的哈夫曼编码HC
{
int m,i,s1,s2,start;
int c,f;
HuffmanTree p;
char *cd;
if(n<=1)
return;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(p=HT+1,i=1;iweight=*w;
p->parent=0;
p->lchild=0;
p->rchild=0;
}
for(;iparent=0;
for(i=n+1;i<=m;++i)//建树
{
j=1;
p=HT;
while((j<=i-1)&&(p[j].parent!=0))//未建结点个数
j++;
s1=j;
while(j<=i-1)
{
if(p[j].parent==0&&p[j].weight<p[s1].weight)//找出最小值s1
s1=j;
j++;
}
p[s1].parent=i;
j=1;
p=HT;
while(j<=i-1&&p[j].parent!=0)//剩余未建结点个数
j++;
s2=j;
while(j<=i-1)
{
if(p[j].parent==0&&p[j].weights2)
{
j=s1;
s1=s2;
s2=j;
}
HT[s1].parent=HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
//从叶子到根逆向求每个字符的哈夫曼编码
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=HT[i].parent;f!=0;c=f,f=HT[f].parent)//从叶子逆向求编码
if(HT[f].lchild==c)//左0右1编码
cd[--start]='0';
else
cd[--start]='1';
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]); //复制串
}
free(cd);
}
void Initialization()//初使化,从终端读入字符集大小n,以及n个字符和n个权值,建树,并存入文件中
{
int num;
int quan;
cout<>num;
n=num;
w=(int*)malloc(n*sizeof(int));//存放权
z=(char*)malloc(n*sizeof(char));//存放字符
cout<<"请依次输入"<<n<<"个字符"<<endl;
char cs[2];
for(i=0;i<n;i++)//存放字符
{
cout<<"第"<<i+1<>cs;
*(z+i)=*cs;
}
cout<<endl<<"请依次输入"<<n<<"个权值"<<endl;
for(i=0;i<=n-1;i++)//存放权
{
cout<<"第"<<i+1<>quan;
*(w+i)=quan;
}
cout<<"字母表为";
for(i=0;i<=n-1;i++)
{
cout<<setw(3)<<*(z+i);
}
cout<<endl;
cout<<"权值表为";
for(i=0;i<=n-1;i++)
{
cout<<setw(3)<<*(w+i);
}
HuffmanCoding(HT,HC,w,n);//建树,编码
cout<<endl<<"各字符对应的编码为:"<<endl;
for(i=1;i<=n;i++)
{
cout<<*(z+i-1)<<"............................";
cout<<HC[i]<<endl;
}
//存入文件htmTree中
FILE *htmTree;
char rt[]={' ','\0'};
if((htmTree=fopen("htmTree.txt","w"))==NULL)
{
cout<<"can not open file"<<endl;
return;
}
fputs(z,htmTree);
for(i=0;i<n+1;i++)
{
fprintf(htmTree,"%5d",*(w+i));
fputs(rt,htmTree);
}
for(i=1;i<=n;i++)
{
fputs(HC[i],htmTree);
fputs(rt,htmTree);
}
fclose(htmTree);
}
void InputMessage()//输入要编译的报文,并将其存入文件tobetran中
{
FILE *tobetran;
char mess[40];
if((tobetran=fopen("tobetran.txt","w"))==NULL)
{
cout<<"不能打开文件"<<endl;
return;
}
cout<<"请输入想要编码"<<endl;
gets(mess);
fputs(mess,tobetran);
fclose(tobetran);
}
void Coding()//读取tobetran中的报文,并编码后存入文件codefile中
{
FILE *tobetran,*codefile;
if((tobetran=fopen("tobetran.txt","rb"))==NULL)
cout<<"不能打开文件"<<endl;
if((codefile=fopen("codefile.txt","wb"))==NULL)
cout<<"不能打开文件"<<endl;
char *tran;//中间变量
tran=(char*)malloc(100*sizeof(char));
int i=1;
while(i==1)
{
if(fgets(tran,100,tobetran)==NULL)
{
cout<<"不能打开文件"<<endl;
break;
}//将tobetran中读取的字符存入tran中
for(i=0;*(tran+i)!='\0';i++)
{
for(j=0;j<=n;j++)
{
if(*(z+j-1)==*(tran+i))//找到第i个字符对应在Z中的位置
fputs(HC[j],codefile);//编码并存入codefile中
}
}
}
fclose(tobetran);
fclose(codefile);
free(tran);
}
void Decoding()//利用已建好的哈夫曼树将codefile中的代码进行译码,并将结果存入文件txtfile中
{
FILE *codef,*txtfile;
if((txtfile=fopen("Textfile.txt","w"))==NULL)
cout<<"不能打开文件"<<endl;
if ((codef=fopen("codefile.txt","r"))==NULL)
cout<<"不能打开文件"<<endl;
char w[1000],v[1000];
int j=0,i=0,m=0;
fgets(w,2000,codef);//将编码存入W中
m=2*n-1;
for(i=0;*(w+i-1)!='\0';i++)
{
if(HT[m].lchild==0&&HT[m].rchild==0) //,无孩子,是叶子结点
{
*(v+j)=*(z+m-1);//找到字符
j++;
m=2*n-1;
i--;
}
else if(*(w+i)=='0') m=HT[m].lchild;//有孩子
else if(*(w+i)=='1') m=HT[m].rchild;
}
*(v+j+1)='\0';
fputs(v,txtfile);//将字符存入文件夹中
fclose(txtfile);
fclose(codef);
}
void Pcode()//将codefile以紧凑可式显式在终端上,每行50个代码,结果存入 CodePrin中
{
FILE * CodePrin,* codefile;
if((CodePrin=fopen("CodePrin.txt","w"))==NULL)
{
cout<<"不能打开文件"<<endl;
return;
}
if((codefile=fopen("codefile.txt","r"))==NULL)
{
cout<<"不能打开文件"<<endl;
return;
}
char *q;
//char *y='\r';
q=(char*)malloc(51*sizeof(char));//存50个字符
do
{//将codefile中的每50个字符存入q中
if(fgets(q,51,codefile)==NULL)
{
cout<<"不能读取文件"<<endl;
break;
}
fputs(q,CodePrin);
//fputs(y,CodePrin);
puts(q);
}while(strlen(q)==50);
free(q);
fclose(CodePrin);
fclose(codefile);
}
void Print(HuffmanTree p,HuffmanTree HT)//打印哈夫曼树,并将其存入TreePrint中
{
if(p!=HT)
{
FILE * TreePrint;
if((TreePrint=fopen("TreePrint.txt","a"))==NULL)
{
cout<<"创建文件失败"<rchild,HT);
cout<<setw(6*number)<weight<weight);
Print(HT+p->lchild,HT);
number--;
fclose(TreePrint);
}
}
void main()
{
char a;
while(a!='Q')
{
cout<<"请选择要执行的命令:"<<endl;
cout<<"I 初使化,建立哈夫曼树; S 输入翻译的报文; E 对报文编码;"<<endl<<" D 对编码进行译码; P 打印代码文件; T 打印哈夫曼树; Q 退出"<>a;
switch(a)
{
case'I':
Initialization();//初使化,建立哈夫曼树
break;
case'S':
InputMessage();//输入要翻译的报文
break;
case'E':
Coding();//读取报文并编码
break;
case'D':
Decoding();//将代码进行译码
break;
case'P':
cout<<"打印编码"<<endl;
Pcode();
break;
case'T':
cout<<"打印哈夫曼树"<<endl;
Print(HT+2*n-1,HT);//打印哈夫曼树
cout<<"原文,编码和译码结果可在文件中查找。";
break;
}
}
free(z);
free(w);
free(HT);
}