哈夫曼树和哈夫曼编码

哈夫曼树的定义

树的结点常常赋予一个表示某种意义的数值,称为结点的权。从树的根结点到任意结点的路径长度与该结点上权值的乘积,称为该结点的带权路径长度,树中所有叶结点的带权路径长度之和称为该树的带权路径长度,记为
在这里插入图片描述

式中,wi是第i个叶结点所带的权值,li是该叶结点到根结点的路径长度。
在含有n个带权叶子结点的二树中,其中带权路径长度(WPL)最小的二叉树称为哈夫曼树,同时也称为最优二 叉树。
例如,下图中3棵二叉树都有4个叶子结点a,b,c,d;,分别带权7,5,2,4。
在这里插入图片描述

它们的带权路径长度分别为
(a)WPL=72+52+22+42=36
(b)WPL=73+53+21+42=46
(c)WPL=71+52+23+43=35
显然(c)中的树为哈夫曼树,它的WPL最小。通过观察,我们可以看到权值越大的叶结点离根结点越近,权值越小的叶结点离根结点越远。

哈夫曼树的构造

根据前面的内容我们已经清楚哈夫曼树的定义和结构了,那么该如何构造出最优二叉树呢?
1)将n个结点看作一个结点数组
2)根据权值对结点数组进行排序,按照权值由小到大排序
3)将结点数组中第一第二个元素(权值最小的两个结点)作为新结点的左右子结点,新结点的权值为左右子结点的权值之和
4)删除选出的两个结点,并将新结点加入到结点数组中
5)重复2),3),4)的操作,直到结点数组中只剩下一个结点
在这里插入图片描述
代码实现

//根据权值对结点排序
	public HTree[] sortHtree(HTree[] nodes){
		for(int i=0;i<nodes.length;i++){
			for(int j=i+1;j<nodes.length;j++){
				if(nodes[i].weight>nodes[j].weight){
					HTree tem=nodes[j];
					nodes[j]=nodes[i];
					nodes[i]=tem;
				}
			}
		}
		return nodes;
	}
	//创建哈夫曼树
	public HTree createTree(int[] weight,String[] strs){
		HTree[] nodes=new HTree[weight.length];//
		for(int i=0;i<nodes.length;i++){
			nodes[i]=new HTree();
			nodes[i].weight=weight[i];
			nodes[i].str=strs[i];
		}
		while(nodes.length>1){
			nodes=sortHtree(nodes);//根据权重对节点排序
			HTree node=new HTree();
			node.left=nodes[0];
			node.right=nodes[1];
			node.weight=nodes[0].weight+nodes[1].weight;
			HTree[] nodes2=new HTree[nodes.length-1];
			for(int i=2;i<nodes.length;i++){
				nodes2[i-2]=nodes[i];
			}
			nodes2[nodes2.length-1]=node;
			nodes=nodes2;
		}
		return nodes[0];
	}

哈夫曼编码

相信很多小伙伴都听说过从二叉树到哈夫曼压缩,那么它是怎么利用哈夫曼来压缩的呢,或者说的它原理是什么?
这涉及到哈夫曼编码了,哈夫曼编码其实很简单,首先构造好哈夫曼树,每个叶结点的哈夫曼码是根据根结点到叶结点的的路径来编的,我们要先定义好编码规则,如向左走为0,向右走为1(0和1没有明确表示左边还是右边),
在这里插入图片描述

//给哈夫曼树每个叶结点编码
	public HTree getCode(HTree root,String code){
		if(root!=null){
			if(root.left==null&&root.right==null){
				String st=code;
				root.code=st;
			}
			getCode(root.left,code+"0");
			getCode(root.right,code+"1");
		}
		return root;
	}

根据字符的编码可以得到字符串的码串,如按照图上字符编码可得字符串aabcc的码串为0 0 101 100 100,一个0、1的储存大小为1个bite,按照哈夫编码,a的存储大小为1个bite,而按ASCII编码,每个字母的存储大小为8个bite。同理,对照其他的字符,可以看到利用哈夫曼可以实现文件压缩。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值