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

📄 hfm.cpp

📁 赫夫曼编/译码器设计 初始化 编码 译码
💻 CPP
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
const SIZE=256;
const SMALLSIZE=20;
struct  HTnode {
	int weight;
	int parent;
	int lchild;
	int rchild;
	char data;
	char code[SIZE];
};
HTnode *HT;
int m,n;
int hashf[SIZE];
char str[SIZE];
void computef()
{
	FILE *in;
	in=fopen("ToBeTran.txt","r");
	if(!in)
	{
		printf("不能打开输入文件\n");
		return;
	}	
	memset(hashf,0,sizeof(hashf));
	char ch;
	while((ch=fgetc(in))!=EOF)		
		hashf[ch]++;
	n=0;
	int i,j=-1;
	for(i=0;i<SIZE;i++)
		if(hashf[i])
			n++;	
	for(i=0;i<SIZE;i++)
		if(hashf[i]!=0)		
			str[++j]=(char)i;
	fclose(in);
}

//s1<=s2
void select(HTnode *HT,int end,int &s1,int &s2)
{
	int min1,min2,i,j,t;
	min1=INT_MAX;
	for(i=1;i<=end;i++)
		if(HT[i].parent==0 && HT[i].weight<min1)
		{
			min1=HT[i].weight;
			s1=i;
		}	
	min2=INT_MAX;
	for(j=1;j<=end;j++)
		if(HT[j].parent==0 && HT[j].weight<min2 && j!=s1)
		{
			min2=HT[i].weight;
			s2=j;
		}
	if(s1>s2)
	{
		t=s1;
		s1=s2;
		s2=t;
	}
}
//初始化
void Init()
{	
	int i,j,*w;	
	computef();
	m=2*n-1;
	w=(int *)malloc(sizeof(int)*n);
	for(i=0,j=-1;i<SIZE;i++)
		if(hashf[i])
			w[++j]=hashf[i];
	HT=(HTnode *)malloc(sizeof(HTnode)*(m+1));
	if(!HT)
	{
		printf("内存不足\n");
		exit(0);
	}
	for(i=1;i<=n;i++)
	{
		HT[i].weight=w[i-1];
		HT[i].parent=0;
		HT[i].lchild=0;
		HT[i].rchild=0;
		HT[i].data=str[i-1];
	}	
	for(;i<=m;i++)
	{
		HT[i].weight=0;
		HT[i].parent=0;
		HT[i].lchild=0;
		HT[i].rchild=0;
		HT[i].data='\0';
		HT[i].code[0]='\0';
	}	
	int s1,s2;
	for(i=n+1;i<=m;i++)
	{
		select(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;
	}
	char *cd;
	int c,f,start;
	cd=(char *)malloc(sizeof(char)*n);
	cd[n-1]='\0';
	for(i=1;i<=n;i++)
	{
		start=n-1;
		for(c=i,f=HT[i].parent;f;c=f,f=HT[f].parent)
			if(HT[f].lchild==c)
				cd[--start]='0';
			else
				cd[--start]='1';
		strcpy(HT[i].code,&cd[start]);		
	}
	free(cd);
	printf("初始化完毕\n");
}
//编码
void Encoding()
{
	FILE *in,*out;
	in=fopen("ToBeTran.txt","r");
	if(!in)
	{
		printf("不能打开输入文件\n");
		return;
	}
	out=fopen("CodeFile.txt","w");
	char ch;
	while((ch=fgetc(in))!=EOF)	
		for(int i=1;i<=n;i++)
			if(HT[i].data==ch)
				fprintf(out,"%s",HT[i].code);
	fprintf(out,"\n");
	printf("编码完毕\n");
	fclose(in);
	fclose(out);
}

//译码
void Decording()
{
	int i,j=-1,find=0;
	char ch,str[SMALLSIZE];
	memset(str,0,sizeof(str));
	FILE *in,*out;
	in=fopen("CodeFile.txt","r");
	if(!in)
	{
		printf("不能打开输入文件\n");
		return;
	}
	out=fopen("TextFile.txt","w");
	while((ch=fgetc(in))!=EOF)
	{		
		if(find)
		{
			memset(str,0,sizeof(str));
			j=-1;
		}
		str[++j]=ch;
		for(i=0;i<=n;i++)
			if(strcmp(HT[i].code,str)==0)
			{
				find=1;
				fprintf(out,"%c",HT[i].data);
				break;
			}
		if(i>n)
			find=0;
	}
	printf("译码完毕\n");
	fclose(in);
	fclose(out);
}

//打印输出代码文件
void Printing()
{
	FILE *in;
	in=fopen("CodeFile.txt","r");
	if(!in)
	{
		printf("不能打开输入文件\n");
		return;
	}
	char ch;
	while((ch=fgetc(in))!=EOF)
		putchar(ch);
}
//打印哈夫曼树(树形)
void TreePrinting()
{
	int i,j;	
	for(i=n;i>=1;i--) 
	{		
		if(i==n)
		{
			printf("\t\t*\n\n");
			printf("\t%c\t\t*\n\n",HT[n-i+1].data);		
		}
		else if(i!=2&&i!=1)
		{
			for(j=0;j<=n-i;j++)
				printf("\t");
			printf("%c\t\t*\n\n",HT[n-i+1].data);		
		}
		else if(i==2)
		{
			for(j=0;j<=n-i;j++)
				printf("\t");
			printf("%c\t\t%c\n\n",HT[n-i+1].data,HT[n].data);		
		}
		else if(i==1)
			printf("\n\n");
	}
	printf("\n");
}
//打印哈夫曼树(树形)
void TreePrint()
{
	int i,j;	
	for(i=1;i<=n;i++)
	{		
		if(i==1)
		{
			printf("\t\t*\n\n");
			printf("\t%c\t\t*\n\n",HT[i].data);		
		}
		else if(i==2)
		{
			for(j=0;j<i;j++)
				printf("\t");
			printf("%c\t\t*\n\n",HT[i].data);		
		}
		else if(i!=2 && i!=1 && i!=n)
		{
			for(j=0;j<i;j++)
				printf("\t");
			printf("%c\t\t%c\n\n",HT[i].data,HT[n].data);		
		}		
		else if(i==n)
			printf("\n\n");
	}
	printf("\n");
}
int getd(int n)
{
	int h=0;
	return h;
}
void show()
{
	int i;
	printf("父节点\t左儿子\t右儿子\t字符\n");
	for(i=1;i<=m;i++)
		printf("%d\t%d\t%d\t%c\n",HT[i].parent,HT[i].lchild,HT[i].rchild,HT[i].data);
}
int main()
{
	FILE *out;
	out=fopen("ToBeTran.txt","w");
	for(int i=0;i<7;i++)
		fputc('a',out);
	for(i=0;i<5;i++)
		fputc('b',out);
	for(i=0;i<2;i++)
		fputc('c',out);
	for(i=0;i<4;i++)
		fputc('d',out);
/*	for(i=0;i<29;i++)
		fputc('e',out);
	for(i=0;i<14;i++)
		fputc('f',out);
	for(i=0;i<7;i++)
		fputc('g',out);
	for(i=0;i<8;i++)
		fputc('h',out);*/
	fclose(out);
	int InitDid,EnDid,DecDid;
 	InitDid=EnDid=DecDid=0;
	while(1)
	{		
		printf("===================================\n");
		printf("\t赫夫曼编/译码器设计\n");
		printf("===================================\n");
		printf("1.初始化\n");
		printf("2.编码\n");
		printf("3.译码\n");
		printf("4.打印输出代码文件\n");
		printf("5.打印输出赫夫曼树\n");
		printf("0.退出\n");
		int choice=0;
		fcloseall();
		scanf("%d",&choice);
		while(choice<0 || choice >5)
		{
			printf("输入错误,请重新输入:");
			scanf("%d",&choice);
		}
		
		switch(choice)
		{
			case 1:				
				if(!InitDid)
				{
					Init();
					InitDid=1;
				}
				break;
			case 2:				
				if(InitDid)
				{
					Encoding();
					EnDid=1;
				}
				else
					printf("还没初始化,请先初始化\n");
				break;
			case 3:				
				if(EnDid)
				{
					Decording();
					DecDid=1;
				}
				else
					printf("还未编码,请先编码\n");
				break;
			case 4:				
				if(EnDid)				
					Printing();
				else
					printf("还未译码,请先编码\n");
				break;
			case 5:TreePrinting();				
				break;
			case 0:printf("谢谢使用,再见!\n");
				return 0;
		}		
	}

	return 0;
}

⌨️ 快捷键说明

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