哈弗曼编码算法
内容比较详细: http://www.cnblogs.com/junyuhuang/p/4127095.html,
代码如下:
package com.qdcz.breadth.demo;
/**
*
* <p>Title: HuffmanCode</p>
* <p>Description:哈弗曼算法实现类
*
* <a href="http://www.cnblogs.com/hibernate3-example/archive/2010/05/15/2492730.html">借鉴资料</a></p>
* <p>Company: 奇点创智</p>
* <p>Version: 1.0</p>
* @author Administrator
* @date 2017年6月6日 下午7:29:41
*/
public class HuffmanCode {
private int charAndWeight[][];// [][0]是 字符,[][1]存放的是字符的权值(次数
private int hfmcodeing[][];// 存放哈弗曼树
private int i=0;// 循环变量
private String hcs[];
public HuffmanCode(int[][] chars) {
charAndWeight=new int[chars.length][2];
charAndWeight=chars;
hfmcodeing=new int[2*chars.length-1][4];// 为哈弗曼树分配空间
}
/**
*
*<p>Title: codeing</p>
*<p>Description:哈夫曼树的实现 </p>
*@return void
*@author Administrator
*@date 2017年6月6日 下午8:08:43
*/
public void codeing(){
int n=charAndWeight.length;
if(n==0) return;
int m=2*n-1;
//初始化哈弗曼树
for (int i = 0; i < n; i++) {
hfmcodeing[i][0]=charAndWeight[i][1];// 初始化哈弗曼树的权值
hfmcodeing[i][1]=0;// 初始化哈弗曼树的根节点
hfmcodeing[i][2]=0;// 初始化哈弗曼树的左孩子
hfmcodeing[i][3]=0;// 初始化哈弗曼树的右孩子
}
for (int i = 0; i <m; i++) {
hfmcodeing[i][0]=0;// 初始化哈弗曼树权值
hfmcodeing[i][1]=0;// 初始化哈弗曼树的根节点
hfmcodeing[i][2]=0;// 初始化哈弗曼树的左孩子
hfmcodeing[i][3]=0;// 初始化哈弗曼树的右孩子
}
//构建哈弗曼树
for (int i = n; i < m; i++) {
int s[]=select(i);// 在哈弗曼树中查找双亲为零的 weight最小的节点
hfmcodeing[s[0]][1]=i;// 为哈弗曼树最小值付双亲
hfmcodeing[s[1]][1]=i;
hfmcodeing[i][2]=s[0];// 新节点的左孩子
hfmcodeing[i][3]=s[1];// 新节点的右孩子
hfmcodeing[i][0]=hfmcodeing[s[0]][0]+hfmcodeing[s[1]][0];// 新节点的权值是左右孩子的权值之和
}
}
/**
*
*<p>Title:select </p>
*<p>Description: 查找双亲为0的weight最小的节点</p>
*@param w
*@return
*@return int[]
*@author Administrator
*@date 2017年6月6日 下午8:12:32
*/
private int[] select(int w) {
int[] s={-1,-1};// s1 最小权值且双亲为零的节点的序号 , i 是循环变量
int j=0;
int min=32767,min1=32767;
for (int i = 0; i < w; i++) {
if(hfmcodeing[i][0]==0){ // 只在尚未构造二叉树的结点中查找(双亲为零的节点)
if(hfmcodeing[i][0]<min){
min1=min;
s[1]=s[0];
min=hfmcodeing[i][0];
s[0]=i;
}else if(hfmcodeing[i][0]<min1){
min1=hfmcodeing[i][0];
s[1]=i;
}
}
}
return s;
}
/**
*
*<p>Title:CreateHcode </p>
*<p>Description:根据哈弗曼树求哈弗 编码</p>
*@return
*@return String[]
*@author Administrator
*@date 2017年6月6日 下午8:13:59
*/
public String[] CreateHcode(){
int n=charAndWeight.length;
int i,f,c;
String hcodeing="";
hcs=new String[n];
for (int j = 0; j <n; j++) {//根据哈夫曼树求哈夫曼编码
c=j;
hcodeing=" ";
f=hfmcodeing[j][1];// f 哈弗曼树的根节点
while(f!=0){// 循序直到树根结点
if(hfmcodeing[f][2]==c){// 处理左孩子结点
hcodeing+="0";
}else{
hcodeing+="1";
}
c=f;
f=hfmcodeing[f][1];
}
hcs[j]=new String(new StringBuffer(hcodeing).reverse());
}
return hcs;
}
/**
*
*<p>Title: show</p>
*<p>Description:对字符串显示编码 </p>
*@param s
*@return
*@return String
*@author Administrator
*@date 2017年6月6日 下午8:15:59
*/
public String show(String s){
String textString="";
char [] c;
int k=-1;
c=new char[s.length()];
c=s.toCharArray();
for (int i = 0; i < c.length; i++) {
k=c[i];
for (int j = 0; j < charAndWeight.length; j++) {
if(k==charAndWeight[j][0]) textString+=hcs[j];
}
}
return textString;
}
/**
*
*<p>Title: reCoding</p>
*<p>Description: 哈弗曼编码反编译</p>
*@param s
*@return
*@return String
*@author Administrator
*@date 2017年6月6日 下午8:16:29
*/
public String reCoding(String s){
String text="";// 存放反编译后的字符
int k=0,m=hfmcodeing.length-1;// 从根节点开始查询
char c[];
c=new char[s.length()];
c=s.toCharArray();
k=m;
for (int i = 0; i < c.length; i++) {
if(c[i]=='0'){
k=hfmcodeing[k][2]; // k的值为根节点左孩子的序号
if(hfmcodeing[k][2]==0&&hfmcodeing[k][3]==0){// 判断是不是叶子节点,条件(左右孩子都为零)
text+=charAndWeight[k][0];
k=m;
}
}
if(c[i]=='1'){
k=hfmcodeing[k][3];// k的值为根节点右孩子的序号
if(hfmcodeing[k][2]==0&&hfmcodeing[k][3]==0){// 判断是不是叶子节点,条件(左右孩子都为零)
text+=charAndWeight[k][0];
k=m;
}
}
}
return text;
}
public static void main(String[] args) {
int[][] chars=new int[5][5];
String s="10101010110";
HuffmanCode code=new HuffmanCode(chars);
code.codeing();
String ss[]=code.CreateHcode();
s=code.show(s);
for (int i = 0; i < ss.length; i++) {
System.out.println(ss[i].toString());
}
}
}