根据输入的各个叶节点的权值,构建一棵最优树,根据最小带全路径,确定由0,1组成的哈弗曼编码。
首先在一个封装类TNode中构建一棵树的元素,比如权值,左节点,右节点,同时在TNode类中构建了哈弗曼编码值,以及判断节点是否为叶子节点
package霍夫曼编码;/***
*@authorluckid
*@version2014_10_11
**/
/*** 定义Huffman编码的节点*/
public classTNode {/***
*@paramweight
*@paramleft
*@paramright*/
/*protected*/ int weight; //权值
TNode left=null; //左节点
TNode right=null; //右节点
String code=null; //霍夫曼编码/*** 构造一个赫夫曼编码节点的实例。设定左右子树和权值*/
public TNode(intweight,TNode left,TNode right){this.weight=weight;this.left=left;this.right=right;
}/***
*@author刘雁冰as
* @date 2015-02-08 1943
**/
public TNode(intweight){this.weight=weight;
}/*** 判断本节点是否为叶子节点
*@returnboolean 为叶子节点则返回true*/
public booleanisLeaf(){return (left==null&&right==null);
}/*** 返回本节点的权值
*@returnnt 本节点的权值*/
public intgetWeight(){returnweight;
}/*** 返回本节点的左孩子节点
*@returnTNode 左孩子节点*/
publicTNode getLeft(){returnleft;
}/*** 返回本节点的右孩子节点
*@returnTNode 右孩子节点*/
publicTNode getRight(){returnright;
}/*** 设置节点的赫夫曼编码
*@paramstr String 被设置的赫夫曼编码*/
public voidsetCode(String str){
code=str;
}/*** 得到节点的赫夫曼编码
*@returnString 被设置的赫夫曼编码*/
publicString getCode(){returncode;
}
}
在Tree类中,构建一棵最优树。首先从键盘读入权值,在这里用1,3,5,7作为测试数据,将读入的测试数据放在一个数组链表中。接着使用迭代器求出最小的叶子节点,然后递归构建一棵最优树,在建构最优树的时候,一次递归需要找出权值最小的叶子节点以及权值次小的叶子节点,两个节点构成一棵子最优树。循序渐进继续递归,直到数组链表中只剩下一个数据,作为整棵最优树的根节点。
测试数据构成的最优子树应该如下:
/*** 定义最优二叉树*/
/*protected*/ TNode root; //二叉树根节点
/*protected*/ ListleafList=new ArrayList(); //存储叶子节点的权值
/*protected*/ ListtempList=new LinkedList(); //临时队列,用于存放待组合的节点
/*protected*/TNode[]leafArr=null; //存放带权节点
/*** 键盘读取各个权值*/
public voidgetLeafWeight(){
Scanner sc=newScanner(System.in);
System.out.println("请输入各个叶节点的权值,按0为结束:");while(sc.hasNextInt()){int i=sc.nextInt();if(i==0)break;
leafList.add(newInteger(i));
}
sc=null;return;
}/*** 找出临时队列中权值最小的节点从队列中移出并返回
*@returnTNode 权值最小的节点*/
publicTNode min(){
Iteratoriter=tempList.iterator();
TNode minNode=iter.next();int min=minNode.getWeight(); //找到最小的节点
TNode tempNode;while(iter.hasNext()){
tempNode=iter.next();if(tempNode.getWeight()
min=tempNode.getWeight();
minNode=tempNode;
}
}
tempList.remove(minNode);//最小的节点移出临时队列//处理垃圾
iter=null;
tempNode=null;returnminNode;
}/*** 根据权值创建叶子节点并加入临时队列*/
public voidmakeLeafNode(){
leafArr=newTNode[leafList.size()];for(int i=0;i
TNode node=newTNode(leafList.get(i).intValue());
leafArr[i]=node;
tempList.add(node);
}
}/*** 根据权值构造最优的二叉树*/
public voidmakeBestTree(){
makeLeafNode();//根据权值创建叶子节点并加入临时队列
TNode minNode1=null;
TNode minNode2=null;
TNode node=null;while(tempList.size()!=1){ //构造最优树
minNode1=min();
minNode2=min();
node=new TNode(minNode1.getWeight()+minNode2.getWeight(),minNode1,minNode2);
tempList.add(node);
}
root=node;
}
构建好了最优树,就可以用HuffmanCode类拓展最优二叉树实现哈弗曼编码。在HuffmanCode类中递归调用huff()方法创建哈弗曼树结构,并且为每个叶子节点赋值,其中左子树赋值0,右子树赋值1
package霍夫曼编码;/***
*@author刘雁冰as
* @date 2015-02-08 1943
**/
/*** 拓展最优二叉树实现Huffman编码
* 赫夫曼编码类*/
public class HuffmanCode extendsTree{publicHuffmanCode(){
init();
}/*** 初始化节点值并构造最优二叉树*/
public voidinit(){super.getLeafWeight();super.makeBestTree();
}/*** 生成赫夫曼编码的递归函数
*
*@paramt TNode 当前遍历节点
*@params String 目前遍历至此的赫夫曼编码*/
/*protected*/public voidhuff(TNode t,String s){if(t.isLeaf()){
t.setCode(s);
}else{
huff(t.left,s+"0");
huff(t.right,s+"1");
}
}/*** 生成赫夫曼编码的外部调用函数*/
public voidmakeHuffmanCode(){
huff(root,"");
}/*** 查看所有的赫夫曼编码值*/
public voidviewHuffmanCode(){for(int i=0;i
System.out.println(leafArr[i].weight+":"+leafArr[i].getCode());
}
}
}
测试类:
package霍夫曼编码;public classApplication {/***
*@author刘雁冰as
* @date 2015-02-08 1943
**/
public static voidmain(String args[]){//TODO Auto-generated method stub
HuffmanCode hu=newHuffmanCode();
hu.makeHuffmanCode();
hu.viewHuffmanCode();
}
}
测试结果如下: