哈夫曼树——C++实现

#include <iostream> 
using namespace std; 
#define MAXBIT 10
#define MAXVALUE 10000

#define MAXLEAF 100
#define MAXNODE MAXLEAF*2-1 


//定义哈夫曼树编码类型
typedef struct{
	char bit[MAXBIT];	//存放叶子结点字符编码过后的二进制编码 
	int start;			//存放叶子结点二进制编码在code[]数组里的起始数组位置
	int length;			//存放二进制编码的位数
}CodeType;   

//定义哈夫曼树结点类型
typedef struct {
	char ch;					//字符
	int weight;					//哈夫曼树结点的权值
	int lchild,rchild,parent;	//哈夫曼树结点的左孩子,右孩子,父节点
}Htnode;   


void createHFMTree(Htnode h[MAXNODE],int n);								//构造哈夫曼树
void showCode(CodeType code[MAXNODE],Htnode h[MAXNODE],int n);				//显示叶子的字符和其对应的二进制编码
void compileCode(char str[],int n,CodeType code[MAXLEAF],Htnode h[MAXNODE]);//输入字符串,得到二进制编码
void decompileCode(char num[],int n,CodeType code[MAXLEAF],Htnode h[MAXNODE]);//输入二进制编码得到字符串

void main(){
	Htnode h[MAXNODE]; 
	CodeType code[MAXLEAF]; 
	char str[100];		//存放输入的需要编译的的字符串
	char num[100];		//存放输入的需要编译的二进制字符串
	int n;				//输入的叶子结点数
	
	//哈夫曼编码器
	cout<<"-----------------哈夫曼编码器------------------\n";
	cout<<"请输入叶子结点数:"; 
	cin>>n;
	createHFMTree(h,n);
	showCode(code,h,n);
	
	//哈夫曼译码器
	cout<<"-----------------哈夫曼译码器------------------\n";
	cout<<"请输入字符:\n";
	cin>>str;
	compileCode(str,n,code,h);
	
	cout<<"请输入需要译码的编码:\n";
	cin>>num;
	decompileCode(num,n,code,h);
}

//构造哈夫曼树
void createHFMTree(Htnode h[MAXNODE],int n){ 
	int i,j,m1,m2,s1,s2; 

	for(i=0;i<2*n-1;i++){	//所有节点初始化
		h[i].weight=0; 
		h[i].parent=-1; 
		h[i].lchild=-1; 
		h[i].rchild=-1; 
	}

	cout<<"请输入叶子节点的字符:";
	for(i=0;i<n;i++){ 
		getchar();
		cin>>h[i].ch;
	} 
	cout<<"请输入叶子节点的权重:";
	for(i=0;i<n;i++){   
		getchar();
		cin>>h[i].weight;
	}

	for(i=0;i<n-1;i++){

		m1=m2=MAXVALUE;		//m1和m2存储叶子结点权值的最小值和次小值
		s1=s2=0;			//s1和s2存储m1和m2的位置
		for(j=0;j<n+i;j++){
			if(h[j].weight<m1&&h[j].parent==-1){ 
				m2=m1;
				s2=s1;
				m1=h[j].weight;
				s1=j; 
			} 
			else if(h[j].weight<m2&&h[j].parent==-1){ 
				m2=h[j].weight;
				s2=j; 
			} 
		} 

		h[n+i].weight=h[s1].weight+h[s2].weight;//父结点的权重是左孩子和右孩子的权重之和
		h[s1].parent=h[s2].parent=n+i; 	
		h[n+i].lchild=s1;h[n+i].rchild=s2;
	}
}

//显示叶子的字符和其对应的二进制编码
void showCode(CodeType code[MAXNODE],Htnode h[MAXNODE],int n){
	int i,j,k,c,p;    
	CodeType cd;
	
	for(i=0;i<n;i++){ 
		code[i].length=0;
		code[i].start=0;
		k=code[i].start;
		cd.start=n-1;
		c=i; 
		p=h[c].parent; 

		while(p!=-1){	//有父节点 
			if(h[p].lchild==c)	//孩子是父节点的左孩子
				cd.bit[cd.start]='0'; 
			else
				cd.bit[cd.start]='1'; 

			cd.start--;  
			c=p;  
			p=h[c].parent;  
		} 

		for(j=cd.start+1;j<n;j++,k++){ 
			code[i].bit[k]=cd.bit[j];   
			code[i].length++;  //length计算存放的二进制编码的位数
		} 
	}

	for(i=0;i<n;i++){ //输出每个叶子节点的哈夫曼编码	  
		cout<<h[i].ch<<"的编码是:";
		for(j=code[i].start;j<code[i].length;j++)
			cout<<code[i].bit[j]; 
		cout<<endl;  
	}
}

//输入字符串,得到二进制编码
void compileCode(char str[],int n,CodeType code[MAXLEAF],Htnode h[MAXNODE]){
	for(int i=0;str[i]!='\0';i++){
		for(int j=0;j<n;j++){
			if(str[i]==h[j].ch){
				for(int k=code[j].start;k<code[j].length;k++)
					cout<<code[j].bit[k];
			}
		}
		cout<<" ";
	}
	cout<<endl<<endl;
}

//输入二进制编码得到字符串
void decompileCode(char num[],int n,CodeType code[MAXLEAF],Htnode h[MAXNODE]){
	int j=2*n-2;  //哈夫曼树根结点的位置

	for(int i=0;num[i]!='\0';i++){
		if(num[i]=='0'){
			j=h[j].lchild;
		}
		else if(num[i]=='1'){
			j=h[j].rchild;
		}
		if(j<n){   //j大于等于n表示的都是除叶子结点以外的哈夫曼树结点   
			cout<<h[j].ch<<" ";
			j=2*n-2;
		}
	}
	cout<<endl;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值