今天晚上算是三天课设集一晚来学习,把代码分析,当然代码也是参照同学的,放这里其实也希望能帮到更多同学吧
自己修改了小小的地方,然后给程序加注释,因为明天早上要给老师讲解的
#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");
}
还要继续理解代码
总得来说课设今晚是最锻炼人的,看我认真起来还是可以的。