Huffman编码 一种数组实现方式

          上一篇博文,提到了无前缀码满足克拉夫特不等式,为了使平均码长最小,我们可以用拉格朗日乘数法来验证,当Li=-logPi时达到极限,接近与H(x).由于是个整数优化问题,当时认为求最小解很困难。但是霍夫曼‘跳出盒子思考’,意思是他先没太在意克拉夫特不等式的限制,而是以另一种方式观察问题,给出了一种算法,也就是大家熟知的Huffman编码。

       Huffman算法最初是在1950年,霍夫曼在麻省理工学院罗伯特.菲诺的信息论课堂上以学期论文的形式提出了这个算法。其实也就相当于我们现在的实验报告之类的东西(鄙人观点),但是就是课堂论文这样的作业,却能诞生这么有意义的想法,我想这也是我们值得学习和敬佩的地方。

         霍夫曼算法核心:通过观察二叉树建立了最佳无前缀码所应具有的一些特性,他采用了简单的递归方法来实现最佳编码。递归的思想,在前面的博文中也有提到,也正是因为对递归算法感兴趣,萌生了采用简单数组方式来实现该算法。


       递归算法中有一个基本思想:往前追溯。在信息论中我们很容易理解,当{p1,p2.....pn}(升序排列)这组符号的最优编码其实等价与缩减符号{p1+p2,p3,p4....pn}这组符号的编码。那么递归就可以起作用了:我们一直往前追溯到当符号个数为2时,我们就直接可以给出编码。然后在往已经编号的码树上添加 叶节点 即可。

       同时,由于Huffman编码已经有各种各样优秀的实现方法,这篇文章是结合自己的探索,采用纯数组的方法来实现,也纯粹是为了加深自己对递归的理解。

       

import java.util.*;
public class Huffman {
	public static void printStr(String a[],String b[]) {
		int i = 0;
		for(i=0;i<a.length&&a[i]!=null;i++) {
			System.out.println(b[i]+"----"+a[i]);
		}
	}
	/***********************************************/
	/*
	tiao_zheng函数,目的是产生缩减符合序列,并且为了使编码后的方差最小
	我们把 概率和 这个新符号 尽量放在高位。
	
	
	*/
  public static String[] tiao_zheng(String a[]) {
  	String b[] ;
  	int i = 0;
  	Double d = 0.0;
		b = Arrays.copyOfRange(a,2,a.length+2);
		d = Double.parseDouble(a[0]) + Double.parseDouble(a[1]);
		b[b.length-2] = Double.toString(d);
	  Arrays.sort(b,0,b.length-1);
		for(i=b.length-2;i>=0;i--) {
			if(Double.parseDouble(b[i]) == d) break;
		}
		b[b.length-1]  = Integer.toString(i);
		return b;
  }
  
  /*********************************************/
  /*
  bian_ma函数的核心就是递归到n=2,然后回溯!
  
  
  */
	public static void bian_ma(String a[]) {
		String b[];
		int i = 0,j = 0;
		int num = 0;
		if(a.length == 2) {
			Arrays.sort(a,0,a.length-1);
			a[0] = "0";
			a[1] = "1";
		
	  }
		else {
		b = tiao_zheng(a);//n-1阶
		int t = Integer.parseInt(b[b.length-1]);
		b = Arrays.copyOfRange(b,0,b.length-1);
		bian_ma(b);//递归
		//当我们把缩减符号编码完成后,就是一些 “修饰” 工作了
		
		a[0] = b[t]+ "0";//添加 叶节点1
		a[1] = b[t] + "1";//添加 叶节点2
		//其它部分保持不变
		int k = 2;
		for(j=0;j<b.length;j++) {
			if(j==t) continue;
			a[k] =b[j];
			k++;
		}
		
	 }
		
		
	}
	/**********************************************/
	
	public static void main(String args[]) {
		String str[] = {"0.1","0.1","0.2","0.2","0.4"};//按升序输入
		String str1[] = Arrays.copyOfRange(str,0,str.length);
    bian_ma(str);
	  printStr(str,str1);
	  
	  
	}
	
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值