欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

哈弗曼编码译码器

程序员文章站 2022-07-14 19:05:36
...
/************************************************************
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 CodeFile(HuffmanTree HT,int n)//对文件进行哈夫曼编码
6. --void TranslationFile(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 CodeFile(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 TranslationFile(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:
				CodeFile(HT,n);
				break;
			case 3:
				TranslationFile(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;
}

哈弗曼编码译码器

哈弗曼编码译码器

哈弗曼编码译码器

哈弗曼编码译码器

哈弗曼编码译码器