哈夫曼树

#include<iostream>
#include<math.h>
#include<string.h>
using namespace std;
#define MAXSIZE 100

//叶子结点定义:
typedef struct{
	double weight;//权
	int parent,lc,rc;
}TNode,*HFMTree;

typedef char** HFMCode;//存储哈夫曼编码,2级指针

//选出2个最小的权值
void Select(HFMTree T,int k,int &s1,int &s2){
	double min = MAXSIZE;
	for(int i=1;i<=k;i++){//最小
		if(T[i].parent==0 && T[i].weight<min){
			min = T[i].weight;
			s1 = i;
		}
	}
	min = MAXSIZE;
	for(int i=1;i<=k;i++){//次最小
		if(i!=s1 && T[i].parent==0 && T[i].weight<min){
			min = T[i].weight;
			s2 = i;
		}
	}
}

//编码,创造哈夫曼树
void HFMCoding(HFMTree &T,HFMCode &C,double w[],int n){//w为1维数组,存放n个字符的权
	if(n<=1)
		return;
	//哈夫曼树没有度为1的结点,所以有n个叶子节点的哈夫曼树有2n-1个结点
	int m = 2*n-1;
	int i,s1,s2;
	HFMTree p = NULL;
	T = new TNode[m+1];//0号单元不
	for(p=T+1,i=1 ; i<=n ; ++i,++p,++w){ //先把叶子结点们初始化,并且附上权值,i从1开始
		p->weight = *w;
		p->lc = 0;
		p->rc = 0;
		p->parent = 0;
	}
	for( ; i<=m ; ++i,++p){ //再把新增的结点初始化,权值默认先为0
		p->weight = 0;
		p->lc = 0;
		p->rc = 0;
		p->parent = 0;
	}
	for(i=n+1;i<=m;++i){
		Select(T,i-1,s1,s2);
		//认亲:
		T[s1].parent = i;
		T[s2].parent = i;
		//认子:
		T[i].lc = s1;
		T[i].rc = s2;
		//孝敬:
		T[i].weight = T[s1].weight+T[s2].weight;
	}
	//从叶子节点到根逆向求每个字符的 HFMCODE
	C = new char*[n+1];
//分配n个字符编码的头指针
	char *cd = new char[n];
	cd[n-1] = '\0';
	for(i=1;i<=n;i++){
		int start=n-1;
		for(int c=i,f=T[i].parent ; f!=0 ; c=f,f=T[f].parent)
			if(T[f].lc==c)
				cd[--start] = '0';
			else
				cd[--start] = '1';
		//为di个字符编码分配空间
		//###########################################
		//i-1是因为s是从0开始是d1元素,主函数为了和s一起从0输出,不然会C的首元素为空,C无法访问
		//##########################################
		C[i-1] = new char[n-start];
		strcpy(C[i-1],&cd[start]);
	}
	delete cd;
}
int main(){
	int n;
	cin>>n;
	char s[20];
	cin>>s;
	double w[20];
	for(int i=0;i<n;i++)
		cin>>w[i];
	HFMCode C;
	HFMTree T;
	HFMCoding(T,C,w,n);
	for(int i=0;i<n;i++){
		cout<<"The "<<s[i]<<" 's Huffman code is:"<<C[i]<<endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值