今天晚上算是三天课设集一晚来学习,把代码分析,当然代码也是参照同学的,放这里其实也希望能帮到更多同学吧
自己修改了小小的地方,然后给程序加注释,因为明天早上要给老师讲解的
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> #define N 100 #define M 2*N struct Infor /*字符--权值*/ { char ch; /*存储字符*/ int weight; /*该字符的权值*/ }Infor[N]; /*结构体数组*/ typedef struct /*哈夫曼树的定义*/ { int weight; /*结点的权值*/ int parent; int LChild; int RChild; }HTNode,HuffmanTree[M]; int length; /*0号单元不用*/ typedef char * HuffmanCode[N+1]; /*记录文件中不相同字符的个数*/ void Select(HuffmanTree ht,int n,int *s1,int *s2) /*s1里面存的是权值最小的下标,s2里面存的是权值第二小的下标*/ { int i; for(i=0;i<=n;i++) if(ht[i].parent==0){ *s1=i; break; } for(i=i+1;i<=n;i++) if(ht[i].parent==0){ /*找双亲为0,找到就退出然后去判断*/ *s2=i; break; } for(i=i+1;i<=n;i++){ if(ht[i].parent==0 && ht[i].weight<*s2) /*确定最小和次小坐标*/ { if(ht[i].weight<*s1) { *s2=*s1; *s1=i; } else *s2=i; } } } void ReadFile()/*读文件的函数*/ { FILE *fp; char c; int i=0,j=0; fp=fopen("data.txt","r"); while((c=fgetc(fp))!=EOF)/*读文件的操作*/ { for(i=0;i<j;i++) if(Infor[i].ch==c) /*如果字符之前出现了,所对应权值+1,也就是在这里统计*/ { Infor[i].weight++; break; } if(i==j) { Infor[j].ch=c; /*读取一个字符,往字符权值结构体里写入一个*/ Infor[j].weight++; j++; } } fclose(fp); length=j; //这就是有多少个权值 } void CrtHuffmanTree(HuffmanTree ht,struct Infor Infor[],int n) /*哈夫曼树的创建*/ { int i,m; int s1,s2; m=2*n-1; for(i=1;i<=n;i++) /*初始化前n个元素成为根结点*/ { ht[i].weight=Infor[i-1].weight; ht[i].LChild=ht[i].RChild=ht[i].parent=0; } for(i=n+1;i<=m;i++) /*初始化后n-1个空元素*/ ht[i].weight=ht[i].LChild=ht[i].RChild=ht[i].parent=0; for(i=n+1;i<=m;i++) { Select(ht,i-1,&s1,&s2); /*在ht的前i-1项中选双亲为0且权值最小的两结点*/ ht[i].weight=ht[s1].weight+ht[s2].weight; /*建新结点,赋权值*/ ht[i].LChild=s1; ht[i].RChild=s2; /*赋新结点左右孩子指针*/ ht[s1].parent=ht[s2].parent=i; /*改s1,s2的双亲指针*/ } } void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int n)/*哈夫曼编码的创建*/ { char *cd; int i,start,c,p; cd=(char *)malloc((n+1)*sizeof(char)); /*临时编码数组*/ cd[n-1]='\0'; /*从后向前逐位求编码,首先放编码结束符*/ for(i=1;i<=n;i++) /*从每个叶子开始,求相应的哈夫曼编码*/ { start=n-1; c=i;p=ht[i].parent; /*c为当前结点,p为其双亲*/ while(p!=0) { --start; if(ht[p].LChild==c) cd[start]='0'; /*左分支得'0'*/ else cd[start]='1'; /*右分支得'1'*/ c=p; p=ht[p].parent; /*上溯一层*/ } hc[i]=(char *)malloc((n-start)*sizeof(char)); /*动态申请编码串空间*/ strcpy(hc[i],&cd[start]); /*复制编码*/ } free(cd); } void WrtCodeFile(struct Infor Infor[],HuffmanCode hc,int n)/*把哈夫曼编码写入文件中*/ { FILE *fp1,*fp2; int i; char c; fp1=fopen("data.txt","r"); fp2=fopen("codeFile.txt","w"); printf("输出哈夫曼编码\n"); while((c=fgetc(fp1))!=EOF){ for(i=0;i<n;i++) if(Infor[i].ch==c) /*当权值所对应的字符与文件所读取的字符相同*/ { fprintf(fp2,"%s",hc[i+1]); /*把这个位上所对应的编码写入到文件中*/ printf("%s",hc[i+1]); break; } } fclose(fp1); fclose(fp2); } void WrtDecodeFile(HuffmanCode hc,struct Infor Infor[],int n)/*哈夫曼译码后写入文件*/ { int i,j=1; char c; char cd[N]; FILE *fp1,*fp2; fp1=fopen("codeFile.txt","r"); fp2=fopen("decodeFile.txt","w"); printf("输出哈夫曼译码\n"); while((c=fgetc(fp1))!=EOF) { cd[j]='\0'; cd[j-1]=c; for(i=1;i<=n;i++) { if(strcmp(hc[i],cd)==0) /*这里和上面是反过来的,如果一编码串和读取到的编码串相同*/ { fprintf(fp2,"%c",Infor[i-1]); /*则在字符串权值结构体中找到对应的字符写入文件*/ printf("%c",Infor[i-1]); j=1; break; } } if(i==n+1) j++; } fclose(fp1); fclose(fp2); } int main() { HuffmanTree ht; HuffmanCode hc; ReadFile(); /*读文本里的内容获取字符权值*/ CrtHuffmanTree(ht,Infor,length); /*创建哈夫曼树*/ CrtHuffmanCode(ht,hc,length); /*将哈夫曼编码写入hc中*/ WrtCodeFile(Infor,hc,length); /*将哈夫曼编码写入文件中*/ printf("\n"); WrtDecodeFile(hc,Infor,length); /*将编码文件里的内容译码并写入文件*/ printf("\n"); }还要继续理解代码
总得来说课设今晚是最锻炼人的,看我认真起来还是可以的。