数据结构课设-哈夫曼树

1、建立哈夫曼树:读入文件(*.souce),统计文件中字符出现的频度,并以这些字符的频度作为权值,建立哈夫曼树。

2、编码:利用已建立好的哈夫曼树,获得各个字符的哈夫曼编码,并对正文进行编码,然后输出编码结果,并存入文件(*.code)中。

3、译码:利用已建立好的哈夫曼树将文件(*.code)中的代码进行译码,并输出译码结果,并存入文件(*.decode)中。

4、利用位操作,实现文件的压缩与解压。(选作)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 100
#define M 2*N-1 
#define MAXINT 32767
#define ch 30
#define NUM 100
typedef char numcode;
typedef char charcode;
typedef char* HuffmanCode[N] ;
typedef struct{
	char data;//字符 
    int weight;//权值 
    int parent; 
    int lchild;
    int rchild; //父结点及左右孩子结点 
}HTNode,HuffmanTree[M]; 

void CrtHuffmanTree(HuffmanTree ht,int w[],int n);
void select(HuffmanTree ht,int pos,int *s1,int *s2);

void CrtHuffmanTree(HuffmanTree ht,int w[],int n)//创建哈夫曼树 
{
    int i,s1,s2,m;
    m=2*n-1;
    for(i=0;i<n;i++){
        ht[i].weight=w[i];ht[i].parent=-1;
        ht[i].lchild=-1;ht[i].rchild=-1;
    }
    for(i=n;i<m;i++){
        ht[i].weight=0;ht[i].parent=-1;
        ht[i].lchild=-1;ht[i].rchild=-1;
    }
    for(i=n;i<m;i++) {
        select(ht,i-1,&s1,&s2);
        ht[i].weight=ht[s1].weight+ht[s2].weight;
        ht[s1].parent=i;
        ht[s2].parent=i;
        ht[i].lchild=s1;
        ht[i].rchild=s2;
    }
}
void select(HuffmanTree ht,int pos,int *s1,int *s2)
{
    int i,j,m1,m2;
    m1=m2=MAXINT;
    for(j=0;j<=pos;j++) {
        if(ht[j].weight<m1&&ht[j].parent==-1){
            m2=m1;*s2=*s1;
            *s1=j;m1=ht[j].weight;
        }
        else if(ht[j].weight<m2&&ht[j].parent==-1){
            m2=ht[j].weight;
            *s2=j;
        }
    }
}
void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int n){
    char *cd;int start,c,p,i;
    cd=(char*)malloc(n*sizeof(char));
    cd[n-1]='\0';   
    for(i=0;i<n;i++){
        start=n-1;c=i;
        p=ht[i].parent;
        while(p!=-1){
            --start;
            if(ht[p].lchild==c) cd[start]='0';
            else    cd[start]='1';
            c=p;p=ht[p].parent;
        }
        hc[i]=(char*)malloc((n-start)*sizeof(char));        
        strcpy(hc[i],&cd[start]);
    }
    free(cd);
}

void printcode(char s[],HuffmanCode hc,int length)//打印输出各字符 
{
    int i; 
    for( i=0;i<length;i++){
        printf("\t\t\t\t%c:",s[i]);
        printf("%s\n",hc[i]);

    }
}
void chartocode(charcode c[],char s[],HuffmanCode hc,int length){ 
	printf("\n");
    int i=0;
    int j;
    FILE *fp;
	if((fp=fopen("编码后文件.txt","wt"))==NULL)
	{
		printf("写文件出错!!按任意键退出。");
		getch();	
		exit(0);	
	}
    while(c[i]!='\0'){    
        for(j=0;j<length;j++){
            if(c[i]==s[j])
            {
                printf("%s",hc[j]);
                fprintf(fp,"%s",hc[j]) ;//向所建文件写一字符串  
			//	printf("%s",hc[j]);
			//	printf("保存成功!!请按任意键继续。\n");
            }
        }
        i++;
    }
    printf("\n");  
	fclose(fp);
	//printf("按任意键返回主菜单!!!");
    //getch();
}
void  numtochar(numcode ns[],HuffmanTree ht,char s[],int length) 
{
	printf("\n");
	  FILE *fp;
	if((fp=fopen("译码后文件.txt","wt"))==NULL)
	{
		printf("写文件出错!!按任意键退出。");
		getch();	
		exit(0);	
	}
	int m; 
	int i=0;
	int key;
	HTNode g;
    m=2*length-1; 
    while(ns[i]!='\0'){
        g=ht[m-1];     
        while(g.lchild!=-1){
            switch(ns[i]){              
            case '0':key=g.lchild;g=ht[g.lchild];break;
            case '1':key=g.rchild;g=ht[g.rchild];break;
            }
            i++;
        }
         printf("%c",s[key]);
         fprintf(fp,"%c",s[key]) ;//向所建文件写一字符串 
         
    }
    	fclose(fp);
}
void print1()
{
	int i;
	system("cls");
	printf("\n\n");
	printf("\t\t|******************************|\n");
	printf("\t\t||****************************||\n");
	printf("\t\t|||                          |||\n");
	printf("\t\t|||   欢迎进入ZERO编码系统   |||\n");
	printf("\t\t|||                          |||\n");
	printf("\t\t||****************************||\n");
	printf("\t\t|******************************|\n");
	printf("\n\t\t\t系统开始启动.........\n");
  	printf("============================================================================\r");
	for(i=1;i<77;i++) 
  {
   Sleep(40);
   printf(">");
	}
}
void print2()
{
	system("cls");
	printf("\n\n\n\n");
	printf("\t\t\t|******************************|\n");
	printf("\t\t\t||****************************||\n");
	printf("\t\t\t|||                          |||\n");
	printf("\t\t\t|||        谢谢使用          |||\n");
	printf("\t\t\t|||                          |||\n");
	printf("\t\t\t||****************************||\n");
	printf("\t\t\t|******************************|\n");
	Sleep(2000);
}
void print3()
{
		system("cls");
	printf("\t\t\t|*******************************|\n");
	printf("\t\t\t|       欢迎来到ZERO编码世界    |\n");
	printf("\t\t\t|*******************************|\n");
	printf("\t\t\t|        1.初始化源文件         |\n");
	printf("\t\t\t|        2.查询字符的编码       |\n");
	printf("\t\t\t|        3.查询编码后的文件     |\n");
	printf("\t\t\t|        4.查询译码后的文件     |\n");
	printf("\t\t\t|-------------------------------|\n");
	printf("\t\t\t|-------------------------------|\n");
	printf("\t\t\t|         0.退出程序            |\n");
	printf("\t\t\t|===============================|\n");
}
void save_in_f1()//创建文件
{
	char ch1[100];
	FILE *fp;
	if((fp=fopen("源文件.txt","wt"))==NULL)
	{
		printf("写文件出错!!按任意键退出。");
		getch();	
		exit(0);	
	}
	printf("请输入原始文档:\n");
    scanf("%s",ch1);
	fprintf(fp,"%s",ch1) ;//向所建文件写一字符串  
	printf("%s",ch1);
	printf("保存成功!!请按任意键继续。\n");
	fclose(fp);
	printf("按任意键返回主菜单!!!");
    getch();
} 
int main(){
	print1();
    HuffmanTree ht;
	HuffmanCode hc;
	charcode c[1000];
	numcode ns[1000];
    int i;
    int n;
	int j,k;
	int loop;
	int count[95]={0};    //计数数组初始化
	int w[N]={0};
    int num=0; 
    int length;
	int choice;
	int back;
	char s[1000]={0}; 
    char b[1000]={0};       //*a[10]定义了一个指针数组	
	FILE *fp;
	loop1:
	if((fp=fopen("e:\\数据结构实验报告\\源文件.txt", "rw"))==NULL)
		printf("读取失败!");
	else  
	{
		i=0;
		while(!feof(fp)) 
		{
			b[i]=fgetc(fp);
			i++;
		//	printf("%d\t",i);
		}
//	printf("\nb:%s",b);
//	system("pause");
	}
	length=i;
//	printf("length:%d\n",length);
 	for( j=0;j<length;j++)
 	{
  		++count[b[j]-32];      //统计每种字符的个数
  	//	printf("%c的权值:%d",b[j],count[b[j]-33]);
  	}
  	for(k=0,j=0;k<95;k++)
   		if(count[k])
  		{
   			w[j]=count[k];
   			s[j]=k+32;
   	//		printf("%c:%d\n",s[j],w[j]);
   			j++;
   		}
	length=j;
//	printf("length:%d",length);
//	system("pause");
    CrtHuffmanTree(ht,w,length);
    CrtHuffmanCode(ht,hc,length);
    loop:
    	{
   	print3();
    scanf("%d",&choice); 
    switch(choice)
	{
		case 1:{
			    system("cls");
			    save_in_f1();
			    CrtHuffmanTree(ht,w,length);
    		    CrtHuffmanCode(ht,hc,length);
    		    printf("返回上一层(1/0)"); 
   				scanf("%d",&back); 
   					if(back==1)
   						goto loop1;
   					print2();
				break;
			}
		case 2:system("cls");
				printcode(s,hc,length);
				printf("返回上一层(1/0)"); 
   				scanf("%d",&back); 
   					if(back==1)
   						goto loop;
   					print2();
				break;//对的 
		case 3:{
				system("cls");
				FILE *fp;
	 				if((fp=fopen("e:\\数据结构实验报告\\待编码文件.txt", "rw"))==NULL)
							printf("读取失败!");
					else{
						    i=0;
					        while(!feof(fp)) 
							{
								c[i]=fgetc(fp);
								printf("%c",c[i]);
								i++;
							}	
					}
   				chartocode(c,s,hc,i); 
   				printf("返回上一层(1/0)"); 
   				scanf("%d",&back); 
   					if(back==1)
   						goto loop;
   					print2();
				break;
				}
		case 4:	{	system("cls");
					FILE *fp;
	 					if((fp=fopen("e:\\数据结构实验报告\\待译码文件.txt", "rw"))==NULL)
							printf("读取失败!");
						else fscanf(fp,"%s",ns);
					fclose(fp);
				//	printf("\n");
					printf("ns:%s",ns);
					numtochar(ns,ht,s,length);
					printf("\n");
					printf("返回上一层(1/0)"); 
   					scanf("%d",&back); 
   					if(back==1)
   						goto loop;
   					print2(); 
					break;
				}
		case 0:print2();break;
	}
	}
}

设计流程图:

猜你喜欢

转载自blog.csdn.net/qq_40384370/article/details/85333041