- 初始化.从终端读入字符集大小n及n个字符和n个权值,建立哈夫曼树,井将它存
于文件HuffmanTree中。
- 编码。利用已建立好的哈夫曼树(如不在内存,则从文件HuffmanTree中读入)。对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中。
- 解码。利用已建立好的哈夫曼树将文件codefile中的代码进行译码,结果存入testfile中。
- 打印代码文件。将文件codefile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件codeprint中。
- 打印哈夫曼树。将已在内存中的哈夫曼树直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint中。
-
# include<stdio.h> # include<stdlib.h> # include<string.h> typedef struct Htree { char c; int weight; int parent,lchild,rchild; }Htree,*HuffmanTree; typedef char ** HuffmanCode; //选择权重值最小的下标 int select(HuffmanTree Ht,int n) { int min,i; for(i=1;i<=n;i++) { if(Ht[i].parent == 0) { min=i; break; } } for(i=i+1;i<=n;i++) { if(Ht[i].parent == 0) { if(Ht[i].weight<Ht[min].weight) min=i; } } return min; } //创建哈夫曼树 void CreatHuffmanTree(HuffmanTree &Ht,int n) { int i,j,m,a,b; m=2*n-1; Ht=new Htree[m+1]; Ht[0].weight=n;//储存顺序表有多少个元素 for(i=1;i<=m;i++) { Ht[i].lchild=Ht[i].rchild=Ht[i].parent=0; } for(i=1;i<=n;i++) { getchar(); scanf("%c",&Ht[i].c); scanf("%d",&Ht[i].weight); } for(j=i;j<=m;j++) { a=select(Ht,j-1); Ht[a].parent=j; b=select(Ht,j-1); Ht[b].parent=j; Ht[j].lchild=a; Ht[j].rchild=b; Ht[j].weight=Ht[a].weight+Ht[b].weight; } } //文件导入叶子结点并创建哈夫曼树 void HuffmanTreeFile(HuffmanTree &Ht,int *n) { FILE *fp; int i,m,k,j,a,b; if((fp=fopen("d:\\HuffmanTree.txt","r"))==NULL) { printf("can't open file\n"); exit(0); } fscanf(fp,"%d",&m); (*n)=m; m=2*m-1; Ht=new Htree[m+1]; if(!Ht) exit(0); for(k=1;k<=m;k++) { Ht[k].lchild=Ht[k].rchild=Ht[k].parent=0; } for(i=1;fscanf(fp,"%d %c",&Ht[i].weight,&Ht[i].c)!=EOF;i++) { printf("第%d条导入成功",i); } for(j=i;j<=m;j++) { a=select(Ht,j-1); Ht[a].parent=j; b=select(Ht,j-1); Ht[b].parent=j; Ht[j].lchild=a; Ht[j].rchild=b; Ht[j].weight=Ht[a].weight+Ht[b].weight; } fclose(fp); } //将哈夫曼的叶子结点写入文件 void WriteFile(HuffmanTree Ht,int n) { FILE *fp; int m,i; if((fp=fopen("d:\\HuffmanTree.txt","w"))==NULL) { printf("can't open file\n"); exit(0); } Ht[0].weight=n; fprintf(fp,"%d\n",Ht[0].weight); for(i=1;i<=n;i++) { if(i<n) { fprintf(fp,"%d %c\n",Ht[i].weight,Ht[i].c); } else { fprintf(fp,"%d %c",Ht[i].weight,Ht[i].c); } } fclose(fp); printf("导入成功!\n"); } //编写叶子结点的哈夫曼编码 void creathuffmancode(HuffmanTree &ht,HuffmanCode &hc,int n) { char *cd; int start,c,f,i; hc=new char*[n+1]; cd=new char[n]; cd[n-1]='\0'; for(i=1;i<=n;i++) { start=n-1; c=i;f=ht[i].parent; while(f!=0) { --start; if(c==ht[f].lchild) cd[start]='0'; else cd[start]='1'; c=f;f=ht[f].parent; } hc[i]=new char[n-start]; strcpy(hc[i],&cd[start]); } delete cd; } //对文本信息进行编码 void tobetransfile(HuffmanTree &ht,HuffmanCode &hc,int n)//对信息编码 { FILE *fp,*fq; HuffmanCode b; b=new char*[100]; char a; int i,j=0; if((fp=fopen("d:\\tobetrans.txt","r"))==NULL) { printf("can't open file\n"); exit(0); } if((fq=fopen("d:\\codefile.txt","w"))==NULL) { printf("can't open file\n"); exit(0); } for(;fscanf(fp,"%c",&a)!=EOF;) { for(i=1;i<=n;i++) { if(a==ht[i].c) { fprintf(fq,"%s",hc[i]); } } } fclose(fp); fclose(fq); printf("编译成功"); } //将编码解译成信息 void slovecode(HuffmanTree &ht,HuffmanCode &hc,int n)//解码 { FILE *fp,*fq; char a[30],b[2]; b[1]='\0'; int i; if((fp=fopen("d:\\codefile.txt","r"))==NULL) { printf("can't open file\n"); exit(0); } if((fq=fopen("d:\\textfile.txt","w"))==NULL) { printf("can't open file\n"); exit(0); } for(;fscanf(fp,"%c",&b[0])!=EOF;) { strcat(a,b); for(i=1;i<=n;i++) { if(!strcmp(a,hc[i])) { fprintf(fq,"%c",ht[i].c); strcpy(a,"\0"); break; } } } fclose(fp); fclose(fq); printf("解码成功"); } //打印信息的编码 void printcode(HuffmanTree &ht,HuffmanCode &hc,int n)//打印 { FILE *fp,*fq; char a[30],b[2]; b[1]='\0'; int i; if((fp=fopen("d:\\codefile.txt","r"))==NULL) { printf("can't open file\n"); exit(0); } if((fq=fopen("d:\\codeprint.txt","w"))==NULL) { printf("can't open file\n"); exit(0); } for(;fscanf(fp,"%c",&b[0])!=EOF;) { strcat(a,b); for(i=1;i<=n;i++) { if(strcmp(a,hc[i])==0) { printf("%c %s\n",ht[i].c,hc[i]); fprintf(fq,"%s\n",hc[i]); strcpy(a,"\0"); break; } } } fclose(fp); fclose(fq); printf("打印成功"); } //前序输出哈夫曼树 void printtree(HuffmanTree ht,int n) { if(n!=0) { printf("%d元素 ",ht[n].weight); printtree(ht,ht[n].lchild); printtree(ht,ht[n].rchild); } } //菜单 void menu() { printf("\n****哈夫曼编码***\n"); printf(" 0 退出系统 \n"); printf(" 1 创建哈夫曼树!\n"); printf(" 2 文件导入哈夫曼树! \n"); printf(" 3 将哈夫曼树写入文件! \n"); printf(" 4 对哈夫曼编码! \n"); printf(" 5 对文件信息编码! \n"); printf(" 6 对文件解码! \n"); printf(" 7 打印编码!\n"); printf(" 8 打印哈夫曼树\n"); } int main() { int i,n,c=1,choice; HuffmanTree ht; HuffmanCode hc; menu(); while(c) { //menu();//选择菜单 scanf("%d",&choice); switch(choice) { case 0: c=0; break; case 1:{ printf("创建哈夫曼树!\n"); printf("输入叶子结点数:\n"); scanf("%d",&n); CreatHuffmanTree(ht,n); break; } case 2:{ printf("文件导入哈夫曼树!\n"); HuffmanTreeFile(ht,&n); break; } case 3:{ printf("将哈夫曼树写入文件\n"); WriteFile(ht,n); break; } case 4:{ printf("对哈夫曼编码!\n"); creathuffmancode(ht,hc,n); break; } case 5:{ printf("对文件信息编码!\n"); tobetransfile(ht,hc,n); break; } case 6:{ printf("对文件解码!\n"); slovecode(ht,hc,n); break; } case 7:{ printf("打印编码!\n"); printcode(ht,hc,n); break; } case 8:{ printf("前序打印哈夫曼树!\n"); printtree(ht,2*n-1); break; } } } return 0; }