哈夫曼算法

编码方式:
1)定长码:每个不同字符的编码长度是规定的,译码是唯一的。
2)变长码:每个不同字符的编码长度不同,比定长码方案好,但译码困难。

前缀码:
1)定义:对任一字符的一个0,1串编码,都不是其他字符编码的前缀
2)作用:前缀性质可以使译码方法非常简单
3)表示:用完全二叉树来表示,即树中任一结点都有2个儿子结点

平均码长B(T)= \sum_{c\epsilon C}f(c)d_{T}(c)其中C表示字符集,c表示任意字符,f(c)表示字符出现的频率,也即权值,dT(c)表示前缀码长。

最优前缀码:使平均码长达到最小的前缀码编码方案称为给定编码字符集C。

1、构造哈夫曼树

        1)根据给定的n个权值 ,构造n棵只有一个根结点的二叉树, n个权值分别是这些二叉树根结点的权。设F是由这n棵二叉树构成的集合;
       2)在F中选取两棵根结点树值最小的树作为左、右子树,构造一颗新的二叉树,置新二叉树根的权值=左、右子树根结点权值之和;
       3)从F中删除这两颗树,并将新树加入F;
       4)重复步骤 2、3,直到F中只含一颗树为止。

贪心策略:每次选择权值最小的子树构造新的二叉树。

2、哈夫曼算法

/*定义树的结构体*/
private static class Huffman implements Comparable{
	Bintree tree; 
	static float weight;
	private Huffman(Bintree tt,float ww){
		tree=tt;
		weight=ww;  //权重
	}
	public int comoareTo(Object x){
		float xw=((Huffman)x).weight;
		if(weight<xw)
			return -1;
		if(weight==xw)
			return 0;
	}
}
/*构造哈夫曼树的算法,其中f[]为字符权值数组*/
private static Bintree huffmanTree(float[]f){
	//生成只有根结点的单结点树
	int n=f.length;
	Huffman[]w=new Huffman [n+1]; //定义二叉树的结构
	Bintree zero=new Bintree();   //构造空子树
	for(int i=0;i<n;i++){
		Bintree x=new Bintree();
		x.makeTree(new MyInteger(i),zero,zero); //左右孩子均为空
		w[n+1]=new Huffman(x,f[i]); // 刻画根结点的权值
	}
	MinHeap H=new MinHeap();  // 创建极小堆
	H.initialize(w,n);    //堆初始化
	/*反复合并最小权值的子树*/
	for(int i=0;i<n;i++){
		Huffman x-(Huffman)H.removeMin();   //取出堆顶元素,即最小元素x,并调整堆
		Huffman y-(Huffman)H.removeMin();   //继续取出堆顶元素,即次小元素y,并调整堆
		Bintree z=new Bintree();  //定义根结点
		z.makeTree(null,x.tree,y.tree);  //构造具有左右孩子 x,y 的子树 z
		Huffman t=new huffman(z,x,weight+y,weight); //计算父结点z的权值
		H.put(t);  //将根的权值插入堆
	}
	return ((Huffman)H.removeMin()).tree; //返回生成树,即哈夫曼树
}

复杂度分析:初始化极小堆时需计算时间O(n),其函数remove() 和put() 运算时间需O(logn),总共n-1次合并需要时间O(nlogn),故哈夫曼算法的时间复杂度为 T(n)=O(nlogn)  

3、贪心选择性质

        已知 c 是字符集,f(x)≤f(c) , f(y)≤f(c),且  
证明:存在 T'',使得\large d_{T''}(x)=d_{T''}(y)( x 与 y 的码长相等),且 x 与 y 为兄弟(权值最小),当 x,y 在任何位置时,需要证明 B(T'') ≤ B(T') ≤ B(T)。如下图:

所以 B(T') ≤ B(T),同理可证B(T'') ≤ B(T') ==> B(T'') ≤ B(T') ≤ B(T) ==> B(T'') ≤ B(T),由假设B(T) ≤ B(T'') ==> B(T) = B(T'')

4、最优子结构性质

已知T'为最优,x,y 为叶结点且同为兄弟,z为其父亲,则f(z) = f(x) + f(y),T = T'- {x,y} U {z}
证明:T'= T- {x,y} 为c’ = c - {x,y} U {z},所以T' 表示字符集c’ 的一个最优前缀码,需证明 B(T)=B(T')+f(x)+f(y) 且T' 是c’ 的最优

②反证:假设T'不是最优,而T''是最优,则

 B(T''') = B(T'')+f(x)+f(y) ≤ B(T')+f(x)+f(y) = B(T),即B(T''') ≤ B(T),得证T'''为最优,与假设T'' 最优矛盾。如下图:


 

 

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值