哈弗曼编码译码器

/************************************************************
Copyright (C), 2017-2018
FileName: huffman.c
Author: Zhao Pengfei 
Date: 12.17-12.18 
Version: 1.20 
Function List: 
1. --void ReadFile(int *key) //读取并解析文件,key指向储存文件的字符总种数
2. --void SelectMin(HuffmanTree HT,int len,int *s1,int *s2)//选取最小的两个s1,s2 
3. --HuffmanTree CreateHuffmanTree(int num)//返回申请的地址  num 叶子节点数 
4. --void CreatHuffmanCode(HuffmanTree HT,int n)//创建哈夫曼编码
5. --void EncodeFile(HuffmanTree HT,int n)//对文件进行哈夫曼编码
6. --void DecodeFile(HuffmanTree HT,int n)//译码	
7. --void menu()//菜单
8. --int main(int argc, char *argv[]) /主函数
History: // 12.19 
<author> <time> <version > <desc>
***********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

typedef struct{
	char ch;//字符 
	char *code;//指向编码表 
	int weight;//权值 
	int parent,lchild,rchild;
}HTNode, *HuffmanTree;

#define MAX 1000 
//文件字符最大数 
#define CODEMAX 20
//编码最大位数 

struct{
	char ch;
	int num;
}b[60];//暂时储存文件解析的数据 

char txt[MAX];//储存文本 
int txtlen;//文件长度 
char codetxt[5000];//存放编码txt后的数组 

void ReadFile(int *key){
	int sum=0;
	int i,j,len;
	int flag=0;
	char filename[10];
	*key=0; 
	for(j=0;j<40;j++){//初始化 
		b[j].ch='\0';
		b[j].num=0;
	}
	printf("请输入文件名:");
	scanf("%s",filename);
	FILE *fp=fopen(filename,"r+");
	if(fp==NULL){
		printf("文件打开失败!按任意键退出\n");
		exit(0);  
	}

	fgets(txt,MAX,fp);
	printf("%s\n",txt);//输出文件 
	for(i=0;i<MAX;i++)
		if(txt[i]=='\0'){
			txtlen=i;//文件长度 
			break;
		}
	for(i=0;i<txtlen;++i,flag=0){//解析文件字符及对应的数量 
		for(j=0;j<(*key);++j){
			if(b[j].ch==txt[i]){
				b[j].num++;
				flag=1;
			}
		}
		if(flag==0){
			b[*key].ch=txt[i];
			b[*key].num+=1;
			(*key)++;
		}	 
	}
	printf("文件共有字符种数:%d\n文件总字符数:%d\n",*key,txtlen); 
	fclose(fp);
} 



void SelectMin(HuffmanTree HT,int len,int *s1,int *s2){ //选取最小的两个s1,s2 
	int i;
	int min=255;
	for(i=1;i<=len;++i)
		if(HT[i].parent==0)
			if(min>HT[i].weight){
				min=HT[i].weight;
				*s1=i;
			}				
	min=255;
	for(i=1;i<=len;++i){
		if(i==(*s1))
			continue;
		if(HT[i].parent==0)
			if(min>HT[i].weight){
				min=HT[i].weight;
				*s2=i;
			}				
	}
				
}

 HuffmanTree CreateHuffmanTree(int num){//返回申请的树地址  num 叶子节点数 
	int m,i;
	int n=num;//叶子节点数 
	int s1=0,s2=0;
	HuffmanTree HT;
	if(n<=1)
		return NULL;		
	m=2*n-1;
	HT=(HuffmanTree)malloc(sizeof(HTNode)*(m+1));

	for(i=1;i<=n;++i){
		HT[i].parent=0;
		HT[i].lchild=0;
		HT[i].rchild=0;
		HT[i].ch=b[i-1].ch;
		HT[i].weight=b[i-1].num;
		HT[i].code='\0'; 
	}
	for(i=n+1;i<=m;++i){
		HT[i].parent=0;
		HT[i].lchild=0;
		HT[i].rchild=0;
		HT[i].ch='\0';
	}
	
	for(i=n+1;i<=m;++i){
		SelectMin(HT,i-1,&s1,&s2);
		HT[s1].parent=i;HT[s2].parent=i;
		HT[i].lchild=s1;
		HT[i].rchild=s2;
		HT[i].weight=HT[s1].weight+HT[s2].weight;
		HT[i].code=0;
	}
	return HT;
}

void CreatHuffmanCode(HuffmanTree HT,int n){
	int i,start,c,f;
	char *cd=(char *)malloc(sizeof(char)*CODEMAX); 
    cd[CODEMAX-1]='\0';   
    for(i=1; i<=n; i++)  
    {      
	    start=CODEMAX-1;  
	    c=i;  
	    f=HT[i].parent;  
	      
	        while(f!=0){  
	            --start;  
	            if(HT[f].lchild==c){  //left--0  right--1
	              
	                cd[start]='0';  
	            }  
	            else{  
	               
	                cd[start]='1';  
	            }  
	            c=f;  
	            f=HT[f].parent;  
	        }  	    
		HT[i].code=(char*)malloc(sizeof(char)*(CODEMAX-start));  		
	    strcpy(HT[i].code,&cd[start]);  //将得到的哈夫曼编码复制到对应的节点	    
    }       
    free(cd);   		
} 

void EncodeFile(HuffmanTree HT,int n){
	int i,j;
	char filename[10];
	printf("请输入编码输出文件名(格式:*.txt):");
	scanf("%s",filename);
	FILE *fp=fopen(filename,"w");
	if(fp==NULL){
		printf("文件建立失败!\n");
		exit(0); 
	}
	
	for(i=0;i<txtlen;++i){//依次读取文件数组的字符 ,找到对应的编码 
		for(j=1;j<=n;++j){
			if(txt[i]==HT[j].ch)
				fprintf(fp,HT[j].code);				
		}
	}
	fclose(fp);
	printf("编码写入文件成功!\n");
}

void DecodeFile(HuffmanTree HT,int n){
	int i,j,f;
	char filename[10];
	char hc;
	printf("请输入要译码文件名(格式:*.txt):");
	scanf("%s",filename);
	FILE *fp=fopen(filename,"r");
	if(fp==NULL){
		printf("文件打开失败!按任意键返回!\n");
		return		; 
	}
	while(!feof(fp)){
		hc=fgetc(fp);
		if(feof(fp))
			break;
		f=2*n-1;
		while(1){
			if(hc=='0') f=HT[f].lchild;	
			else f=HT[f].rchild;			
			if(HT[f].lchild==0&&HT[f].rchild==0){
				printf("%c",HT[f].ch);
				break;
			}
			else hc=fgetc(fp);
		}
	}
	
	fclose(fp);
}
void menu(){
	system("cls");
	printf("\n\n\n\n");
	printf("\t\t|-----------哈夫曼编译码器 -----------|\n");
	printf("\t\t|\n");
	printf("\t\t|\t1.读取文件并建立哈夫曼树\n");
	printf("\t\t|\t2.导出编码文件\n");
	printf("\t\t|\t3.译码并打印\n");
	printf("\t\t|\t4.显示编码表\n");
	printf("\t\t|\t0.退出\n");
	printf("\t\t|\n");
	printf("\t\t|-------------------------------------|\n\n");
	printf("\t\t\t请按照正确逻辑顺序操作!\n");
	printf("\n");
	printf("\t\t\t请选择(0-4):");
	
} 
int main(int argc, char *argv[]) {
	int i;
	int n;//字符总类型数 
	int choice;
	HuffmanTree HT; 
	system("color f0\n"); //白底黑字
	menu();
	scanf("%d",&choice);	
	while(choice)
	{
		switch(choice)
		{
			case 1:
				ReadFile(&n); 
				HT=CreateHuffmanTree(n);//构建哈夫曼树 
				CreatHuffmanCode(HT,n);//创建哈弗曼编码 
				break; 
			case 2:
				EncodeFile(HT,n);
				break;
			case 3:
				DecodeFile(HT,n);
				break;
			case 4:
				for(i=1;i<=n;++i)
					printf(">>>%2d\tch:%c\tweight:%d\tcode:%s\n",i,HT[i].ch,HT[i].weight,HT[i].code);
				break; 
			default:
				break;
		}
		getch();
		menu();
		scanf("%d",&choice);
	}

	return 0;
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值