⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 huffman.cpp

📁 huffman 编译码器的实现
💻 CPP
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
#define MAXVALUE 10000
typedef struct{
	int weight;
	int flag;
	int parent;
	char ch;
	int lchild;
	int rchild;
}HafNode;
typedef struct{
	int bit[MAX];
	int start;
	int weight;
	char ch;
}Code;
typedef struct{
	char bit[MAX];
	char ch;
	int weight;
}Coding;
 /*---------------生成哈夫曼树的函数---------------*/
void CreatHfmTree(int weight[],char ch[],int n,HafNode haffTree[]){
	int i,j,m1,m2,x1,x2;
	for (i=0;i<2*n-1;i++){
		if(i<n){
			haffTree[i].weight=weight[i];
			haffTree[i].ch=ch[i];
		}
		else
			haffTree[i].weight=0;
		haffTree[i].parent=-1;
		haffTree[i].flag=0;
		haffTree[i].lchild=-1;
		haffTree[i].rchild=-1;
	}
	for (i=0;i<n-1;i++)
	{
		m1=m2=MAXVALUE;
		x1=x2=0;
		for (j=0;j<n+i;j++){
			if (haffTree[j].weight<m1&&haffTree[j].flag==0){
				m2=m1;x2=x1;m1=haffTree[j].weight;x1=j;
			}
			else if(haffTree[j].weight<m2 && haffTree[j].flag==0)
			{
				m2=haffTree[j].weight;x2=j;
			}
		}
		haffTree[x1].parent= n + i;
		haffTree[x2].parent = n + i;
		haffTree[x1].flag = 1;
		haffTree[x2].flag = 1;
		haffTree[n+i].weight = haffTree[x1].weight + haffTree[x2].weight;
		haffTree[n+i].lchild = x1;
		haffTree[n+i].rchild = x2;
	}
	FILE *fp;
	fp=fopen("huffman.txt","w+");
	printf("%d\n",n);
	fprintf(fp,"%d\n",n);
	for (i=0;i<n;i++) 
		fprintf(fp,"%c %d %d %d\n",haffTree[i].ch,haffTree[i].parent,haffTree[i].lchild,haffTree[i].rchild);
	for (i=n;i<2*n-1;i++)
		fprintf(fp,"%d %d %d\n",haffTree[i].parent,haffTree[i].lchild,haffTree[i].rchild); 
	fclose(fp);
}
/*-----------------哈夫曼编码函数-------------------*/
void HaffmanCode (HafNode haffTree[],int n,Code haffCode[]){
	Code *cd=( Code *) malloc (sizeof (Code));
	int i,j,child,parent; 
	for (i=0; i<n; i++){
		cd->start=n-1;
		cd->weight=haffTree[i].weight;
		cd->ch=haffTree[i].ch;
		child=i;
		parent=haffTree[child].parent;
		while (parent !=-1){
			if (haffTree[parent].lchild==child)
				cd->bit[cd->start]=0;
			else
				cd->bit[cd->start]=1;
			cd->start--;
			child =parent;
			parent=haffTree[child].parent;
		}
		for (j=cd->start+1; j<n; j++)
			haffCode[i].bit[j]=cd->bit[j];
		haffCode [i].start = cd->start+1;
		haffCode [i].weight=cd->weight;
		haffCode [i].ch=cd->ch;
	}
} 
/*-------------------初始化操作--------------------*/
void InitHfmTree(int weight[],char ch[]){
	FILE *fp;
	int i,j,n;
	char ch1,wj[15];
	printf("现在进行初始化操作。。。\n请选择:\nA.键盘输入 B.文件输入\n");
	scanf("%c",&ch1);
	if (ch1=='A'){
		printf("请输入字符集大小n:\n");
		scanf("%d",&n);
	}
	if (ch1=='B'){
		printf("请输入文件名:\n");
		scanf("%s",wj);
		fp=fopen(wj,"r"); 
		fscanf(fp,"%d",&n);
	} 
	HafNode *myHaffTree=(HafNode *)malloc(sizeof (HafNode)*(2*n+1));
	Code *myHaffCode =(Code *)malloc (sizeof (Code)*n);
	for (i=0;i<n;i++){
		if (ch1=='A'){
			printf("请输入字符和权值:\n");
			scanf("%s %d",&ch[i],&weight[i]);
		}
		if (ch1=='B')
			fscanf(fp,"%s %d",&ch[i],&weight[i]);
	}
	if (ch1=='B')
		fclose(fp);
	CreatHfmTree(weight,ch,n,myHaffTree);
	HaffmanCode(myHaffTree,n,myHaffCode);
	fp=fopen("hfmtree.txt","w+"); 
	for (i=0;i<n;i++){
		printf("%c %d ",myHaffCode[i].ch,myHaffCode[i].weight);
		fprintf(fp,"%c %d ",myHaffCode[i].ch,myHaffCode[i].weight);
		for ( j=myHaffCode[i].start; j<n; j++){ 
			printf("%d",myHaffCode[i].bit[j]);
			fprintf(fp,"%d",myHaffCode[i].bit[j]);
		}
		fprintf(fp,"\n");
		printf("\n");
	}
	fclose(fp);
	printf("初始化成功!\n");
}
 /*-----------------文件编码过程-----------------*/
void FileCoding(){
	FILE *fp,*fp1,*fp2;
	char zf[500];
	fp=fopen("hfmtree.txt","r");
	Coding ch[100];
	char c;
	int i=0;
	while (feof(fp)==0){ 
		fscanf(fp,"%s %d %s",&ch[i].ch,&ch[i].weight,&ch[i].bit);
		i++;
	}
	fclose(fp); 
	printf("现在进行编码操作。。。\n请选择:\nA.键盘输入 B.文件输入\n");
	scanf("%s",&c);
	if (c=='A'){
		printf("请输入字符串:\n");scanf("%s",zf);
	} 
	char ch1[20],ch2[20];
	int j;
	if (c=='B'){
		printf("请输入正文的文件名:\n");
		scanf("%s",&ch1);
		fp1=fopen(ch1,"r");
	}
	printf("请输入保存结果的文件名:\n");
	scanf("%s",&ch2); 
	fp2=fopen(ch2,"w+");
	if (c=='A'){
		int len,k;
		len=strlen(zf);
		for (k=0;k<len;k++)
			for (j=0;j<i;j++)
				if (ch[j].ch==zf[k]){
					fprintf(fp2,"%s",ch[j].bit);
					printf("%s",ch[j].bit);
				}
				printf("\n"); 
	}
	if (c=='B'){
		while(feof(fp1)==0){ 
			fscanf(fp1,"%c",&c);
			for (j=0;j<i;j++)
				if (ch[j].ch==c){
					fprintf(fp2,"%s",ch[j].bit);
					printf("%s",ch[j].bit);
				}
		}
		fprintf(fp2,"\n"); 
		printf("\n");
		fclose(fp1);
	} 
	fclose(fp2);
	printf("编码过程完成!同时已将结果存入%s中.\n\n",ch2);
}
/*----------------------译码操作---------------------*/
void DeCoding(){ 
	FILE *fp,*fp1; 
	fp=fopen("huffman.txt","r");
	int i,n;
	fscanf(fp,"%d",&n);
	HafNode *myHaffTree=(HafNode *)malloc(sizeof (HafNode)*(2*n+1));
	for (i=0;i<n;i++)
		fscanf(fp,"%s %d %d %d\n",&myHaffTree[i].ch,&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
	for (i=n;i<2*n-1;i++)
		fscanf(fp,"%d %d %d\n",&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
	fclose(fp);
	printf("请输入译码文件的文件名:\n");
	char ch1[20],ch2[20];
	scanf("%s",ch1);
	printf("请输入结果文件的文件名:\n");
	scanf("%s",ch2); 
	fp=fopen(ch1,"r");
	fp1=fopen(ch2,"w+");
	char ch;
	i=2*n-2;
	while (!feof(fp)){
		fscanf(fp,"%c",&ch); 
		if (ch=='0') //若编码为0,则找此结点的左孩子;
			i=myHaffTree[i].lchild;
		if (ch=='1') //若编码为1,则找此结点的右孩子; 
			i=myHaffTree[i].rchild; 
		if (i<n){
			printf("%c",myHaffTree[i].ch);
			fprintf(fp1,"%c",myHaffTree[i].ch);
			i=2*n-2;
		}
	}
	printf("\n");
	fprintf(fp1,"\n");
	fclose(fp);
	fclose(fp1);
	printf("译码过程完成!已将结果存入%s中.\n\n",ch2);
}
/*------------------打印代码文件-----------------*/
void PrintCodeFile() {
	FILE *fp1,*fp2;
	printf("请输入输入文件的文件名:\n");
	char ch1[20],ch2[20];
	scanf("%s",ch1);
	printf("请输入结果保存的文件名:\n");
	scanf("%s",ch2);
	fp1=fopen(ch1,"r");
	fp2=fopen(ch2,"w+");
	int count=0;
	char ch;
	while (!feof(fp1)){
		fscanf(fp1,"%c",&ch); 
		printf("%c",ch);
		fprintf(fp2,"%c",ch);
		count++;
		if (count==50){
			printf("\n");
			fprintf(fp2,"\n");
			count=0;
		}
	}
	printf("\n");
	fprintf(fp2,"\n");
	fclose(fp1);
	fclose(fp2);
	printf("打印代码过程完成!已将结果存入%s中.\n\n",ch2);
}
/*-------------------打印哈夫曼树结点-----------------*/
void PrintTreeCode(HafNode *huf,int n,int p,FILE *fp){
	int i;
	if (n==-1)
		return;
	PrintTreeCode(huf,huf[n].rchild,p+1,fp);
	for (i=0;i<p;i++){
		printf(" ");
		fprintf(fp," ");
	}
	if (p>=0&&huf[n].rchild==-1){
		printf("---");
		printf("%c\n",huf[n].ch); //如果此结点为叶子结点,则将此结点输出;
		fprintf(fp,"---%c\n",huf[n].ch);
	}
	else {
		printf("@\n");            //如果此结点为非叶子结点,则输出"@";
		fprintf(fp,"@\n");
	}
	PrintTreeCode(huf,huf[n].lchild,p+1,fp);
}
/*-----------------打印哈夫曼树的操作----------------*/
void PrintTree(){ 
	FILE *fp;
	fp=fopen("huffman.txt","r");
	int i,n;
	fscanf(fp,"%d",&n);
	HafNode *myHaffTree=(HafNode *)malloc(sizeof (HafNode)*(2*n+1));
	for (i=0;i<n;i++)
		fscanf(fp,"%s %d %d %d\n",&myHaffTree[i].ch,&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
	for (i=n;i<2*n-1;i++)
		fscanf(fp,"%d %d %d\n",&myHaffTree[i].parent,&myHaffTree[i].lchild,&myHaffTree[i].rchild);
	fclose(fp);
	printf("请输入保存结果的文件名:\n");
	char ch1[20];
	scanf("%s",ch1);
	fp=fopen(ch1,"w+");
	PrintTreeCode(myHaffTree,2*n-2,0,fp);
	fclose(fp);
	printf("打印哈夫曼树过程完成!同时已将结果存入%s中.\n\n",ch1); 
}
/*-------------------------打印表单----------------------*/
void Sheet(){
	printf("*******************************************************************************\n");
	printf("***** ******************** 欢迎使用哈夫曼编/译码器 ********************* *****\n");
	printf("***** ******************** ************************ ********************* *****\n");
	printf("***** C.编码    D.译码   T.印哈夫曼树   P.印代码文件   E.退出 *****\n");
	printf("*******************************************************************************\n");
}
int main(){
	int n=4;
	int weight[100];
	char ch[100],cha;
	Sheet();
	InitHfmTree(weight,ch);
	while (1){
		printf("请输入要执行的操作:\nC.编码   D.译码   T.印哈夫曼树   P.印代码文件   E.退出\n");
		printf("请输入要执行的操作:\n");
		scanf("%s",&cha);
		if (cha=='E')
			break; 
		switch (cha){
		case 'C':FileCoding();break; //执行编码操作
		case 'D':DeCoding();break; //执行译码操作
		case 'T':PrintTree();break; //打印哈夫曼树
		case 'P':PrintCodeFile();break; //打印代码文件
		}
	}
	return 0; 
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -