首页 > 编程语言 > 详细

java实现哈弗曼编码

时间:2015-02-08 20:39:23      阅读:294      评论:0      收藏:0      [点我收藏+]

根据输入的各个叶节点的权值,构建一棵最优树,根据最小带全路径,确定由0,1组成的哈弗曼编码。

首先在一个封装类TNode中构建一棵树的元素,比如权值,左节点,右节点,同时在TNode类中构建了哈弗曼编码值,以及判断节点是否为叶子节点

package 霍夫曼编码;
/**
 * 
 * @author luckid
 * @version 2014_10_11
 * 
 */

/**
 * 定义Huffman编码的节点
 */

public class TNode {
    /**
     * 
     * @param weight
     * @param left
     * @param right
     */

    /*protected*/ int weight;                                        //权值
    TNode left=null;                                            //左节点
    TNode right=null;                                            //右节点
    String code=null;                                            //霍夫曼编码
/**
 *  构造一个赫夫曼编码节点的实例。设定左右子树和权值
 */
    public TNode(int weight,TNode left,TNode right){
        this.weight=weight;
        this.left=left;
        this.right=right;
        
    }
    
    /**
     * 
     * @author 刘雁冰as
     * @date 2015-02-08 1943
     * 
     */
    public TNode(int weight){
        this.weight=weight;
    }
    
    /**
     * 判断本节点是否为叶子节点
     * @return boolean 为叶子节点则返回true 
     */
    public boolean isLeaf(){
        return (left==null&&right==null);
    }
    
    /**
     * 返回本节点的权值
     * @return nt 本节点的权值
     */
    public int getWeight(){
        return weight;
    }
    
    /**
     * 返回本节点的左孩子节点
     * @return TNode 左孩子节点
     */
    public TNode getLeft(){
        return left;
    }
    
    /**
     * 返回本节点的右孩子节点
     * @return TNode 右孩子节点
     */
    public TNode getRight(){
        return right;
    }
    
    /**
     * 设置节点的赫夫曼编码
     * @param str String 被设置的赫夫曼编码
     */
    public void setCode(String str){
        code=str;
    }
    
    /**
     * 得到节点的赫夫曼编码
     * @return String 被设置的赫夫曼编码
     */
    public String getCode(){
        return code;
    }
    
}

 

  

在Tree类中,构建一棵最优树。首先从键盘读入权值,在这里用1,3,5,7作为测试数据,将读入的测试数据放在一个数组链表中。接着使用迭代器求出最小的叶子节点,然后递归构建一棵最优树,在建构最优树的时候,一次递归需要找出权值最小的叶子节点以及权值次小的叶子节点,两个节点构成一棵子最优树。循序渐进继续递归,直到数组链表中只剩下一个数据,作为整棵最优树的根节点。

测试数据构成的最优子树应该如下:

技术分享

 

    /**
     * 定义最优二叉树
     */
    /*protected*/ TNode root;                                                                            //二叉树根节点
    /*protected*/ List<Integer>leafList=new ArrayList<Integer>();            //存储叶子节点的权值
    /*protected*/ List<TNode>tempList=new LinkedList<TNode>();            //临时队列,用于存放待组合的节点
    /*protected*/TNode[]leafArr=null;                                                            //存放带权节点
    
    /**
     * 键盘读取各个权值
     */
    public void getLeafWeight(){
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入各个叶节点的权值,按0为结束:");
        while(sc.hasNextInt()){
            int i=sc.nextInt();
            if(i==0)
                break;
            leafList.add(new Integer(i));
        }
        sc=null;
        return ;
    }
    
    /**
     * 找出临时队列中权值最小的节点从队列中移出并返回
     * @return TNode 权值最小的节点
     */
    public TNode min(){
        Iterator<TNode>iter=tempList.iterator();
        TNode minNode=iter.next();
        int min=minNode.getWeight();                         //找到最小的节点
        TNode tempNode;
        while(iter.hasNext()){
            tempNode=iter.next();
            if(tempNode.getWeight()<min){
                min=tempNode.getWeight();
                minNode=tempNode;
            }
        }
        tempList.remove(minNode);                              //最小的节点移出临时队列
         //处理垃圾
        iter=null;
        tempNode=null;
        return minNode;
    }
    
    /**
     * 根据权值创建叶子节点并加入临时队列
     */
    public void makeLeafNode(){
        leafArr=new TNode[leafList.size()];
        for(int i=0;i<leafList.size();i++){
            TNode node=new TNode(leafList.get(i).intValue());
            leafArr[i]=node;
            tempList.add(node);
        }
    }
    
    /**
     * 根据权值构造最优的二叉树
     */
    public void makeBestTree(){
        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 extends Tree{
    public HuffmanCode(){
        init();
    }
    
    /**
     * 初始化节点值并构造最优二叉树
     */
    public void init(){
        super.getLeafWeight();
        super.makeBestTree();
    }
    
    /**
     * 生成赫夫曼编码的递归函数
     * 
     * @param t TNode 当前遍历节点
     * @param s String 目前遍历至此的赫夫曼编码
     */
    /*protected*/public  void huff(TNode t,String s){
        if(t.isLeaf()){
            t.setCode(s);
        }
        else{
            huff(t.left,s+"0");
            huff(t.right,s+"1");
        }
    }
    
    /**
     * 生成赫夫曼编码的外部调用函数
     */
    public void makeHuffmanCode(){
        huff(root,"");
    }
    
    /**
     * 查看所有的赫夫曼编码值
     */
    public void viewHuffmanCode(){
        for(int i=0;i<leafArr.length;i++){
            System.out.println(leafArr[i].weight+":"+leafArr[i].getCode());
        }
    }
    
}

测试类:

package 霍夫曼编码;

public class Application {

    /**
     * 
     * @author 刘雁冰as
     * @date 2015-02-08 1943
     * 
     */
    public static void main(String args[]){
        // TODO Auto-generated method stub
        HuffmanCode hu=new HuffmanCode();
        hu.makeHuffmanCode();
        hu.viewHuffmanCode();
    }

}

测试结果如下:

技术分享

java实现哈弗曼编码

原文:http://www.cnblogs.com/luckid/p/4280379.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!