数据结构实验任务四:哈夫曼编码

该代码为数据结构实验任务四:哈夫曼树及哈夫曼编码实现。

输出第一行,为字符串中各个字符出现的次数

接下来为用表表示哈夫曼树

下一行为对字符串中各字符的编码

String Encode:字符串编码

String Decode:译码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxS 100			//字符串最大长度 
#define maxE 10				//最大样本组数 
#define maxC 6				//最大编码位数 





//树结点结构
typedef struct{
	int weight;
	char ch;
	int parent,lchild,rchild;	
}HF;

//函数声明 
void Encode(HF* hf,int n);				//字符编码 
char* SEncode(char *a,int n);			//字符串编码 
char* SDecode(char *a);					//字符串译码 
void PCodes(); 							//显示字符编码 
void DFS(HF* hf,int n);					//DFS遍历哈夫曼树 
void Show(HF* hf,int n);				//显示哈夫曼树 
int  count(char *a);					//统计字符串中字符的出现频率 
void Itr(HF* hf,int n);					//哈夫曼遍历迭代 
HF* Halfman(char *a,HF* hf);			//构建哈夫曼编码树 
int  Read(char a[][maxS]);				// 读取字符串

 
//全局变量 
int fre[26];	//字母出现频率 
char Codes[26][maxC];	//每个字母的编码 


//输出编码
void PCodes(){
	for(int i=0;i<26;i++){
		if(Codes[i][0]!='\0'){
			printf("%c:%s	",'a'+i,Codes[i]);
		}
	}
	printf("\n");
} 
 //DFS遍历哈夫曼树并编码
void DFS(HF* hf,int n){
 	static char code[maxC]="";
 	static int cunt=0;
 	int flag = 0;
	 if(hf[n].lchild!=-1){
	 	code[cunt++] = '0';
	 	DFS(hf,hf[n].lchild);
	 	cunt--;
	 	flag = 1; 
	 }
	 if(hf[n].rchild!=-1){
	 	code[cunt++] = '1';
	 	DFS(hf,hf[n].rchild);
	 	cunt--;
	 	flag = 1;
	 }
	 if(flag==0){
	 	code[cunt] = '\0';
	 	strcpy(Codes[hf[n].ch-'a'],code);
	 }	
 } 
 //查看哈夫曼树
 void Show(HF* hf,int n){
 	int i=0;
 	printf("Halfman tree:\nAi  C   W   L   C   P"); 
 	while(i<n){
 		printf("\n%d : %c %3d %3d %3d %3d",i,hf[i].ch,hf[i].weight,hf[i].lchild,hf[i].rchild,hf[i].parent);
 		i++;
	 }
	 printf("\n");
 } 
//统计频率,并返回总类别数 
int  count(char *a){
	int rs=0;
	for(int i=0;i<26;i++){
		fre[i] = 0;
	}
	for(int i=0;i<maxS;i++){
		if(a[i]>='a'&&a[i]<='z'){
			fre[a[i]-'a']+=1;
		}else{
			a[i] = '\0';
			break;
		}
		
	}
	for(int i=0;i<26;i++){
		if(fre[i]!=0)rs++;
	}
	return rs;
}

//哈夫曼树迭代并输出 
void Itr(HF* hf,int n){
	int min1,min2,turn,pos1,pos2;
	printf("The frequence of letter:\n");
	for(int i=0;i<n;i++){
		printf("%c:%d	",hf[i].ch,hf[i].weight);
	}
	printf("\n");
	for(int  i=n;i<2*n-1;i++){
		
		min1 = -1;
		min2 = -1;
		
		for(int j=i-1;j>=0;j--){
			if(hf[j].parent==0){
				if(min2==-1){
					min2 = hf[j].weight;
					pos2 = j;
					continue;
				}else if(min1==-1){
					min1 = hf[j].weight;
					pos1 = j;
					continue;
				}
			}
		
			if(min1>min2){
				turn = min1;
				min1 = min2;
				min2 = turn;
				
				turn = pos1;
				pos1 = pos2;
				pos2 = turn;
			}
			
			if(hf[j].weight<min2&&hf[j].parent==0){
				min2 = hf[j].weight;
				pos2 = j;
			}
		}
		if(min1>min2){
				turn = min1;
				min1 = min2;
				min2 = turn;
				
				turn = pos1;
				pos1 = pos2;
				pos2 = turn;
			}
		
		hf[i].lchild = pos1;
		hf[i].rchild = pos2;
		hf[i].weight = min1+min2;
		hf[i].parent= 0;
		hf[i].ch='#';
		hf[pos1].parent = i;
		hf[pos2].parent = i;
	}
	Show(hf,2*n-1);
}

//哈夫曼树
 HF* Halfman(char *a,HF* hf){
 	int num,n=0;
 	num = count(a);		//统计频率,加载fre数组
 	hf = (HF*)malloc(sizeof(HF)*(2*num-1));
 	char *Sencode,*Sdecode; 
	 //动态设计,加载HF数组初始化 
	 for(int i=0;i<26;i++){
	 	if(fre[i]!=0){
	 		hf[n].lchild=-1;
			hf[n].rchild=-1; 
	 		hf[n].ch = 'a'+i;
	 		hf[n].weight=fre[i];
	 		hf[n].parent = 0;
	 		n++;
		 }
	 } 

	 //HF数组迭代
	 	 printf("\n                  =================FZC===============                 \n\n");
	 printf("[EXP]:\n");
	 Itr(hf,n);
	 printf("\n");
	 //对每个字符进行编码 
	 Encode(hf,n);
	 PCodes();
	 //对字符串进行编码 
	 Sencode = SEncode(a,strlen(a));
	 printf("\nString Encode:%s\n",Sencode);
	 //对字符串进行解码
	 Sdecode = SDecode(Sencode);
	 printf("\nString Decode:%s\n\n",Sdecode);

	 return hf;
 } 

//字母编码
void Encode(HF* hf,int n){
	//清空原始数据 
	for(int i=0;i<26;i++){
		strcpy(Codes[i],"");
	} 
	DFS(hf,2*n-2); 
}
//字符串编码 
char* SEncode(char *a,int n){
	char *rs = (char*)malloc(sizeof(char)*n*maxC);
	int cunt=0;
	for(int i=0;i<n;i++){
		strcpy(rs+cunt,Codes[a[i]-'a']);
		cunt+=strlen(Codes[a[i]-'a']);
	}
	return rs;
} 
//字符串解码
char* SDecode(char *a){
	char tmp[maxC]="";
	char *rs = (char*)malloc(sizeof(char)*maxS);
	int cunt = 0;
	int tcunt=0;
	for(int i=0;i<strlen(a);i++){
		tmp[tcunt++] = a[i];
		tmp[tcunt] = '\0';
		for(int j=0;j<26;j++){
			if(strcmp(tmp,Codes[j])==0){
				rs[cunt++] = 'a'+j;
				tcunt = 0;
			}
		}
	}
	rs[cunt]='\0';
	return rs;
} 
//读取字符串
int  Read(char a[][maxS]){
	int i,j;
	printf("Please input the Strings and end with 0\n");
	for(i=0;i<maxE;i++){
		for(int j=0;j<maxS;j++)a[i][j]='#';
	}
	for(i=0;i<maxE;i++){
		scanf("%s",a[i]);
		if(a[i][0]=='0')break;
	}
	return i;
}
int main(){
	char a[maxE][maxS];
	HF *halfman[maxE];
	int num=0;
	num = Read(a);	//读取字符串 
	printf("FOLLWING OUTPUT:\n\n");
	for(int i=0;i<num;i++){			
		halfman[i] = Halfman(a[i],halfman[i]);		//对每一组数据进行哈夫曼树构建 
	}
	return 0;
}

该代码仅供参考,有任何问题欢迎交流。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值