数据结构课程设计-12月30号

今天晚上算是三天课设集一晚来学习,把代码分析,当然代码也是参照同学的,放这里其实也希望能帮到更多同学吧

自己修改了小小的地方,然后给程序加注释,因为明天早上要给老师讲解的

#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");
}
还要继续理解代码

总得来说课设今晚是最锻炼人的,看我认真起来还是可以的。


你可能感兴趣的:(数据结构课程设计-12月30号)