#include<bits/stdc++.h> #define N 8 typedef struct hm { char ch; char code[20]; } HuffM; typedef struct s { char ch; int frq; } mytype; typedef struct bt { struct bt *lchild; mytype dt; struct bt *rchild; } bitree; int g_flag=0; int Encoding(HuffM d[]); int PreOrderPrint(bitree *HT,int cont); void PrintCodeFile(); void PrintTextFile(); int Decoding(HuffM d[]); int reaData(mytype d[])//载入数据 { FILE * fp; int i=0; fp=fopen("data.txt","r"); if(NULL==fp) { return -1; } while(!feof(fp)) { fscanf(fp,"%c",&(d[i].ch)); fscanf(fp,"%d",&(d[i].frq)); fseek(fp,2,SEEK_CUR); i++; if(i==N-2) break; } g_flag=1; fclose(fp); return 0; } int reaHFData(HuffM d[])//从hfmTree.txt文件读取数据 { FILE * fp; int i=0,td; char c,data[20]; fp=fopen("hfmTree.txt","r"); if(NULL==fp) { printf("打开哈夫曼编码数据文件出错。 "); return -1; } while(1) { fscanf(fp,"%c%d%s",&c,&td,data); if(feof(fp)) break; d[i].ch=c; strcpy(d[i].code,data); i++; fseek(fp,2,SEEK_CUR); } g_flag=1; fclose(fp); return 0; } int printData(mytype d[]) //数据显示 字符 频度 { int i=0; if(g_flag<1) { printf("请先载入数据文件。 "); return 0; } for(; i<N-3; i++) { printf("%c %d ",d[i].ch,d[i].frq); } return 0; } int printHFData(HuffM d[]) //显示哈夫曼树 字符 编码 { int i=0; if(g_flag<1) { printf("请先载入数据文件。 "); return 0; } for(; i<N-3; i++) { printf("%c %s ",d[i].ch,d[i].code); } return 0; } int sort(mytype d[])//对数据频度大小排序 建哈夫曼树时调用 { int i,j; mytype temp; if(g_flag<1) { printf("请先载入数据文件。 "); return 0; } for(i=0; i<N-4; i++) { for(j=0; j<N-4-i; j++) { if(d[j].frq>d[j+1].frq) { temp=d[j]; d[j]=d[j+1]; d[j+1]=temp; } } } } int sortHMC(HuffM d[])//对哈夫曼树字符排序 译码文件时调用 { int i,j; HuffM temp; if(g_flag<1) { printf("请先载入数据文件。 "); return 0; } for(i=0; i<N-4; i++) { for(j=0; j<N-4-i; j++) { if(d[j].ch>d[j+1].ch) { temp=d[j]; d[j]=d[j+1]; d[j+1]=temp; } } } } int sort1(bitree* temp[N],int n)//对新的数据重新 频度大小排序 建树时调用 { int i,j; bitree* tmp; for(i=0; i<n-1; i++) { for(j=0; j<n-1-i; j++) { if(temp[N-3-n+j]->dt.frq>temp[N-3-n+j+1]->dt.frq) { tmp=temp[N-3-n+j]; temp[N-3-n+j]=temp[N-3-n+j+1]; temp[N-3-n+j+1]=tmp; } } } } bitree * createbt(mytype d[])//建哈夫曼树 { bitree* head=NULL; bitree* temp[N]= {NULL}; int i=0; if(g_flag<1) { printf("请先载入数据文件。 "); return 0; } sort(d); while(i<N-3) { temp[i]=(bitree *)malloc(sizeof(bitree)); temp[i]->dt=d[i]; temp[i]->lchild=NULL; temp[i]->rchild=NULL; i++; } i=0; while(i<N-4) { head=(bitree *)malloc(sizeof(bitree)); head->dt.ch='*'; head->dt.frq=temp[i]->dt.frq + temp[i+1]->dt.frq; head->lchild=temp[i]; head->rchild=temp[i+1]; temp[i+1]=head; temp[i]=NULL; sort1(temp,N-i-4); i++; } g_flag = 11; return head; } bitree * destroybt(bitree * head)//销毁哈夫曼树,释放空间 递归调用 { bitree *temp; if(head==NULL) return NULL; temp=head; if(head->lchild) head->lchild=destroybt(temp->lchild); if(head->rchild) head->rchild=destroybt(temp->rchild); free(head); head=NULL; return NULL; } void HuffManCoding(bitree *BT, int len,FILE *fp) //哈夫曼树编码 利用 static函数 并写入文件 { static int a[10]; int i; if(g_flag<11) { printf("请先建立哈夫曼树。 "); return ; } if(BT!=NULL) { if(BT->lchild==NULL&&BT->rchild==NULL) { fprintf(fp,"%c %d ",BT->dt.ch,BT->dt.frq); for(i=0; i<len; i++) fprintf(fp,"%d",a[i]); fprintf(fp," "); } else { a[len]=0; HuffManCoding(BT->lchild, len+1,fp); a[len]=1; HuffManCoding(BT->rchild, len+1,fp); } } } int menu() { int n; printf("***************************** "); printf("字符集和频度操作: "); printf(" 1.载入数据文件。 "); printf(" 2.显示数据。 "); printf(" 3.排序。 "); printf("哈夫曼树操作: "); printf(" 4.建立哈夫曼树。 "); printf(" 5.写入哈夫曼编码文件。 "); printf(" 6.显示哈夫曼编码文件。 "); printf(" 7.销毁哈夫曼树。 "); printf("哈夫曼编译码操作: "); printf(" 8.载入哈夫曼编码。 "); printf(" 9.显示哈夫曼编码。 "); printf(" 10.编码ToBeTran文件. "); printf(" 11.译码CodeFile文件. "); printf(" 12.打印CodeFile文件. "); printf(" 13.打印译码TextFile文件. "); printf(" 14.打印哈夫曼树. "); printf(" 15.退出 "); printf("***************************** "); printf("请输入选择:"); while(1) { scanf("%d",&n); if(n>0&&n<=15) break; printf("输入错误,请重输:"); } system("cls"); return n; } int printHuffManfile() //输出哈夫曼树 字符 频度 编码 { FILE * fp; char data[50],c; int d; fp=fopen("hfmTree.txt","r"); if(NULL==fp) { printf("打开文件哈夫曼编码错误。 "); return -1; } while(1) { fscanf(fp,"%c%d%s",&c,&d,data); if(feof(fp)) break; printf("%c %d %s ",c,d,data); fseek(fp,2,SEEK_CUR); } fclose(fp); } main() { mytype data[N]= {0}; HuffM hmdata[N]= {0}; int flag; int choose,cont; FILE *fp; bitree *bthead=NULL; cont=0; g_flag=0;//刚开始时数据为空。 while(1) { choose=menu(); switch(choose) { case 1: flag=reaData(data); if(-1==flag) { printf("Open data.txt file error! "); return 0; } break; case 2: printData(data); break; case 3: sort(data); break; case 4: bthead=createbt(data); break; case 5: fp=fopen("hfmTree.txt","w+"); if(NULL==fp) { printf("写入哈夫曼编码错误! "); return 0; } HuffManCoding(bthead,0,fp); g_flag=111; fclose(fp); break; case 6: printHuffManfile(); break; case 7: if(g_flag<11) { printf("请先建立哈夫曼树。 "); break; } bthead=destroybt(bthead); g_flag=1; break; case 8: flag=reaHFData(hmdata); if(-1==flag) { printf("Open data.txt file error! "); return 0; } sortHMC(hmdata); break; case 9: printHFData(hmdata); break; case 10: Encoding(hmdata); break; case 11: Decoding(hmdata); break; case 12: PrintCodeFile(); break; case 13: PrintTextFile(); break; case 14: PreOrderPrint(bthead,cont); break; case 15: destroybt(bthead); return 0; break; } } } int Encoding(HuffM d[])//编码 { FILE *fp,*pfc; char data[256]= {0},c; fp=fopen("ToBeTran.txt","r"); pfc=fopen("CodeFile.txt","w"); if(NULL==fp) { printf("打开文件ToBeTran.txt出错,编码未完成. "); return -1; } if(NULL==pfc) { fclose(fp); printf("CodeFile.txt出错,编码未完成. "); return -1; } while(1) { fread(&c,1,1,fp); if(c>='a'&&c<='z') c-=32; if(c>='A'&&c<='Z') { fprintf(pfc,"%s",d[c-'A'+1].code); } else if (c==' ') fprintf(pfc,"%s",d[0].code); else fprintf(pfc,"%c",c); if(feof(fp)) break; } fclose(fp); fclose(pfc); } int Decoding(HuffM d[])//编码 { FILE *fp, *pfc; char data[20] = { 0 },c; int i;//, flag fp = fopen("ToBeTran.txt", "r"); pfc = fopen("TextFile.txt", "w"); if (NULL == fp) { printf("打开文件ToBeTran.txt出错,译码未完成. "); return -1; } if (NULL == pfc) { fclose(fp); printf("TextFile.txt出错,译码未完成. "); return -1; } while (1) { fread(&c, 1, 1, fp); if (c=='1'|| c=='0') { // return 1; for(i=0; i<27; i++) { data[i]=c; while (strcmp(d[i].code,data)==0) fprintf(pfc,"%c",d[i].ch); } } else fprintf(pfc,"%c",c); if (feof(fp)) break; } fclose(fp); fclose(pfc); return 1; } void PrintCodeFile() { FILE *fc; int flag; char ch; printf("打印编码后的文件: "); fc=fopen("CodeFile.txt", "r"); if (NULL==fc) { printf("打印编码后的文件失败!! "); exit(0); } flag = 1; while (!feof(fc)) { ch = fgetc(fc); if (ch == -1) { printf("结束打印 "); } else { printf("%c", ch); if (flag <= 49) flag++; else { flag = 1; printf(" "); } } } fclose(fc); } void PrintTextFile() { FILE *fc; int flag; char ch; printf("打印译码后的文件: "); fc=fopen("TextFile.txt", "r"); if (NULL==fc) { printf("打印译码后的文件失败!! "); exit(0); } flag = 1; while (!feof(fc)) { ch = fgetc(fc); if (ch == -1) { printf("结束打印 "); } else { printf("%c", ch); if (flag <= 49) flag++; else { flag = 1; printf(" "); } } } fclose(fc); } int PreOrderPrint(bitree *HT,int cont) { int n = 2 * (N - 3) - 1, i; if(NULL!=HT) { for (i = 0; i<cont; i++) printf(" "); printf("%c%d ",HT->dt.ch,HT->dt.frq); PreOrderPrint(HT->lchild, cont+1); PreOrderPrint(HT->rchild, cont+1); } return 1; }