c语言实现哈夫曼编/译码器

本文介绍了如何使用C语言实现哈夫曼编码算法,包括创建哈夫曼树、文件导入、编码、解码、以及打印编码和哈夫曼树的过程。
摘要由CSDN通过智能技术生成

         

  • 初始化.从终端读入字符集大小n及n个字符和n个权值,建立哈夫曼树,井将它存

于文件HuffmanTree中。

  • 编码。利用已建立好的哈夫曼树(如不在内存,则从文件HuffmanTree中读入)。对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中。
  • 解码。利用已建立好的哈夫曼树将文件codefile中的代码进行译码,结果存入testfile中。
  • 打印代码文件。将文件codefile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件codeprint中。
  • 打印哈夫曼树。将已在内存中的哈夫曼树直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint中。
  • # include<stdio.h>
    # include<stdlib.h>
    # include<string.h>
    
    typedef struct  Htree 
    {
    	char c;
    	int weight; 
    	int parent,lchild,rchild;
    }Htree,*HuffmanTree;
    
    typedef char ** HuffmanCode;
    //选择权重值最小的下标 
    int  select(HuffmanTree Ht,int n)
    {	int min,i;
    	for(i=1;i<=n;i++)
    	{
    		if(Ht[i].parent == 0)
    		{
    			min=i;
    			break;
    		}
    	}
    	for(i=i+1;i<=n;i++)
    	{
    		if(Ht[i].parent == 0)
    		{
    			if(Ht[i].weight<Ht[min].weight)	
    				min=i;
    		}
    	}
    	return min;
    }
    //创建哈夫曼树 
    void CreatHuffmanTree(HuffmanTree &Ht,int n)
    {
    	int i,j,m,a,b;
    	m=2*n-1;
    	Ht=new Htree[m+1];
    	Ht[0].weight=n;//储存顺序表有多少个元素 
    	for(i=1;i<=m;i++)
    	{
    		Ht[i].lchild=Ht[i].rchild=Ht[i].parent=0; 
    	}
    	for(i=1;i<=n;i++)
    	{	getchar();
    		scanf("%c",&Ht[i].c);
    		scanf("%d",&Ht[i].weight);
    	}
    	for(j=i;j<=m;j++)
    	{
    		a=select(Ht,j-1);
    		Ht[a].parent=j;
    		b=select(Ht,j-1);
    		Ht[b].parent=j;
    		Ht[j].lchild=a;
    		Ht[j].rchild=b;
    		Ht[j].weight=Ht[a].weight+Ht[b].weight;
    	}
    }
    //文件导入叶子结点并创建哈夫曼树 
    void HuffmanTreeFile(HuffmanTree &Ht,int *n)
    {
    	FILE *fp;
    	int i,m,k,j,a,b;
    	if((fp=fopen("d:\\HuffmanTree.txt","r"))==NULL)
    	{
    		printf("can't open file\n");
    		exit(0);
    	}
    	fscanf(fp,"%d",&m);
    	(*n)=m;
    	m=2*m-1;
    	Ht=new Htree[m+1];
    	if(!Ht) exit(0);	
    	for(k=1;k<=m;k++)
    	{
    		Ht[k].lchild=Ht[k].rchild=Ht[k].parent=0;
    	}
    	for(i=1;fscanf(fp,"%d %c",&Ht[i].weight,&Ht[i].c)!=EOF;i++)
    	{
    		printf("第%d条导入成功",i);
    	}
    	for(j=i;j<=m;j++)
    	{
    		a=select(Ht,j-1);
    		Ht[a].parent=j;
    		b=select(Ht,j-1);
    		Ht[b].parent=j;
    		Ht[j].lchild=a;
    		Ht[j].rchild=b;
    		Ht[j].weight=Ht[a].weight+Ht[b].weight;
    	}
    	fclose(fp);
     }
    //将哈夫曼的叶子结点写入文件 
    void WriteFile(HuffmanTree Ht,int n)
    {	FILE  *fp;
    	int m,i;
    	if((fp=fopen("d:\\HuffmanTree.txt","w"))==NULL)
    	{
    		printf("can't open file\n");
    		exit(0);
    	}
    	Ht[0].weight=n;
    	fprintf(fp,"%d\n",Ht[0].weight);
    	for(i=1;i<=n;i++)
    	{
    		if(i<n)
    		{
    			fprintf(fp,"%d %c\n",Ht[i].weight,Ht[i].c);
    		}
    		else 
    		{
    			fprintf(fp,"%d %c",Ht[i].weight,Ht[i].c);
    		}
    	}
    	fclose(fp);
    	printf("导入成功!\n"); 
    }
    //编写叶子结点的哈夫曼编码 
    void creathuffmancode(HuffmanTree &ht,HuffmanCode &hc,int n)
    {
    	char *cd;
    	int start,c,f,i;
    	hc=new char*[n+1];
    	cd=new char[n];
    	cd[n-1]='\0';
    	for(i=1;i<=n;i++)
    	{
    		start=n-1;
    		c=i;f=ht[i].parent;
    		while(f!=0)
    		{	--start;
    			if(c==ht[f].lchild) 
    				cd[start]='0';
    			else 
    				cd[start]='1';
    			c=f;f=ht[f].parent;
    		 } 
    		hc[i]=new char[n-start];
    		strcpy(hc[i],&cd[start]);
    	}
    	delete cd;
    }
    //对文本信息进行编码 
    void tobetransfile(HuffmanTree &ht,HuffmanCode &hc,int n)//对信息编码 
    {
    	FILE  *fp,*fq;
    	HuffmanCode b;
    	b=new char*[100];
    	char a;
    	int i,j=0;
    	if((fp=fopen("d:\\tobetrans.txt","r"))==NULL)
    	{
    		printf("can't open file\n");
    		exit(0);
    	}
    	if((fq=fopen("d:\\codefile.txt","w"))==NULL)
    	{
    		printf("can't open file\n");
    		exit(0);
    	}
    	for(;fscanf(fp,"%c",&a)!=EOF;)
    	{
    		for(i=1;i<=n;i++)
    		{
    			if(a==ht[i].c)
    			{
    				fprintf(fq,"%s",hc[i]);
    			}
    		}
    	}
    	fclose(fp);
    	fclose(fq);
    	printf("编译成功");
    }
    //将编码解译成信息 
    void slovecode(HuffmanTree &ht,HuffmanCode &hc,int n)//解码 
    {
    	FILE  *fp,*fq;
    	char a[30],b[2];
    	b[1]='\0';
    	int i;
    	if((fp=fopen("d:\\codefile.txt","r"))==NULL)
    	{
    		printf("can't open file\n");
    		exit(0);
    	}
    	if((fq=fopen("d:\\textfile.txt","w"))==NULL)
    	{
    		printf("can't open file\n");
    		exit(0);
    	}
    	for(;fscanf(fp,"%c",&b[0])!=EOF;)
    	{	strcat(a,b);
    		for(i=1;i<=n;i++)
    		{	
    			if(!strcmp(a,hc[i]))
    			{
    				fprintf(fq,"%c",ht[i].c);
    				strcpy(a,"\0");
    				break;
    			}
    		}
    	}
    	fclose(fp);
    	fclose(fq);
    	printf("解码成功");
    }
    //打印信息的编码 
    void printcode(HuffmanTree &ht,HuffmanCode &hc,int n)//打印 
    {
    	FILE  *fp,*fq;
    	char a[30],b[2];
    	b[1]='\0';
    	int i;
    	if((fp=fopen("d:\\codefile.txt","r"))==NULL)
    	{
    		printf("can't open file\n");
    		exit(0);
    	}
    	if((fq=fopen("d:\\codeprint.txt","w"))==NULL)
    	{
    		printf("can't open file\n");
    		exit(0);
    	}
    	for(;fscanf(fp,"%c",&b[0])!=EOF;)
    	{	strcat(a,b);
    		for(i=1;i<=n;i++)
    		{	
    			if(strcmp(a,hc[i])==0)
    			{	
    				printf("%c %s\n",ht[i].c,hc[i]);
    				fprintf(fq,"%s\n",hc[i]);
    				strcpy(a,"\0");
    			
    				break;
    			}
    		}
    	}
    	fclose(fp);
    	fclose(fq);
    	printf("打印成功");
    }
    //前序输出哈夫曼树 
    void printtree(HuffmanTree ht,int n)
    {	if(n!=0)
    	{
    		printf("%d元素 ",ht[n].weight);
    		printtree(ht,ht[n].lchild);
    		printtree(ht,ht[n].rchild);
    	}
    }
    //菜单 
    void menu()
    {
    	printf("\n****哈夫曼编码***\n");
    	printf("   0 退出系统  \n");
    	printf("   1 创建哈夫曼树!\n");
    	printf("   2 文件导入哈夫曼树!  \n");
    	printf("   3 将哈夫曼树写入文件! \n");
    	printf("   4 对哈夫曼编码! \n");
    	printf("   5 对文件信息编码!  \n");
    	printf("   6 对文件解码! \n");
    	printf("   7 打印编码!\n");
    	printf("   8 打印哈夫曼树\n");
    } 
    
    int main()
    {	
    	int i,n,c=1,choice;
    	HuffmanTree ht;
    	HuffmanCode hc;
    	menu(); 
    	while(c)
    	{	//menu();//选择菜单 
    		scanf("%d",&choice);
    		switch(choice)
    		{
    			case 0: c=0;
    					break;
    			case 1:{
    				printf("创建哈夫曼树!\n");
    				printf("输入叶子结点数:\n"); 
    				scanf("%d",&n); 
    				CreatHuffmanTree(ht,n);
    				break;
    			}
    			case 2:{
    				printf("文件导入哈夫曼树!\n");
    				HuffmanTreeFile(ht,&n);
    				break;
    			} 
    			case 3:{
    				printf("将哈夫曼树写入文件\n");
    				WriteFile(ht,n); 
    				break;
    			} 
    			case 4:{
    				printf("对哈夫曼编码!\n");
    				creathuffmancode(ht,hc,n); 
    				break;
    			} 
    			case 5:{
    				printf("对文件信息编码!\n");
    				tobetransfile(ht,hc,n);
    				break;
    			}
    			case 6:{
    				printf("对文件解码!\n");
    				slovecode(ht,hc,n);
    				break;
    			} 
    			case 7:{
    				printf("打印编码!\n"); 
    				printcode(ht,hc,n);
    				break;
    			}
    			case 8:{
    				printf("前序打印哈夫曼树!\n"); 
    				printtree(ht,2*n-1);
    				break;
    			}
    		}
    	}	
    	return 0;
    }

  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值