huffman编码

 这里随便写了个用java实现的哈夫曼编码的算法(二叉树表示)。    

  

/**

 *@(#)岑村高科

 */

package cn.javayy.struct;

 

/**

 *定义了一种接口,要进行编码的最小单元类必需实现些接口

 *@authorboss

 *

 *createon:下午10:56:592009-5-19

 */

publicinterface Combinable<T> extends Comparable<T> {

 

    T combinate(T a,T b);

   

}

 

=====================================================================================

/**

 *@(#)岑村高科

 */

package cn.javayy.struct;

 

/**

 *thehuffmantreeClass

 *<p>哈夫曼树,包括当前节点数据信息,左节点,右节点信息。

 *@authorboss

 *

 *createon:下午10:16:232009-5-19

 */

publicclass HuffmanTree<T extends Combinable<T>> implements Comparable<HuffmanTree<T>>{

 

    /**therootofhuffmantree*/

    private T root;

    /**theleftnodeofhuffmantree*/

    private HuffmanTree<T> left;

    /**therightnodeofhuffmantree*/

    private HuffmanTree<T> right;

    /**哈夫曼编码字符串,如:0000110*/

    private String huffmanCodeString = "";

    /**是否对最终生成的哈夫曼进行过编码操作*/

    privatestaticbooleanisSettedHuffmanCoderString = false;

   

    public T getRoot() {

       returnroot;

    }

 

 

    publicvoid setRoot(T root) {

       this.root = root;

    }

 

 

    public HuffmanTree<T> getLeft() {

       returnleft;

    }

 

 

    publicvoid setLeft(HuffmanTree<T> left) {

       this.left = left;

    }

 

 

    public HuffmanTree<T> getRight() {

       returnright;

    }

 

 

    publicvoid setRight(HuffmanTree<T> right) {

       this.right = right;

    }

 

 

    /**

     *重写此方法用于递归合并节点后进行排序操作

     */

    @Override

    publicint compareTo(HuffmanTree<T> o) {

       // TODO Auto-generated method stub

       return o.getRoot().compareTo(this.getRoot());

    }

   

    @Override

    public String toString(){

       return"the root:" + this.getRoot()

              + "\r\nthe left:" + this.getLeft()

              + "\r\nthe right:" + this.getRight();

    }

   

    /**

     *对最终生成的树进行哈夫曼编码,使每个叶子节点生成01的路径编码

     */

    privatevoid setHuffmanCoderString(){

       HuffmanTree<T> left = this.getLeft();

       //如果有左节点则在路径中追加"0"

       if(left != null){

           left.huffmanCodeString = this.huffmanCodeString + "0";

           left.setHuffmanCoderString();//递归编码

       }

       HuffmanTree<T> right = this.getRight();

       //如果有右节点则在路径中追加"1"

       if(right != null){

           right.huffmanCodeString = this.huffmanCodeString + "1";

           right.setHuffmanCoderString();//递归编码

       }

    }

   

    publicvoid printHuffmanCoderString(){

       //打印最终生成树的哈夫曼编码前要进行编码操作,

       //且此操作只执行一次,所以用全局标识变量判断

       if(!HuffmanTree.isSettedHuffmanCoderString){

           this.setHuffmanCoderString();

           HuffmanTree.isSettedHuffmanCoderString = true;//标识已执行过编码

       }

       //如果是叶子节点(即要编码的单元),则打印出编码信息,如果是非叶子结点(中间临时生成的节点),则不打印

       if(this.left == null && this.right == null)

           System.out.println("the " + this.getRoot() + " huffmanCoder:" + this.huffmanCodeString);

       if(this.left != null)

           this.left.printHuffmanCoderString();//递归打印

       if(this.right != null)

           this.right.printHuffmanCoderString();//递归打印

    }

   

}

 

===================================================================================

 

/**

 *@(#)岑村高科

 */

package cn.javayy.struct;

 

import java.util.Collections;

import java.util.LinkedList;

import java.util.List;

 

/**

 *用类用于生成一个哈夫曼树

 *@authorboss

 *

 *createon:下午10:51:392009-5-19

 */

publicclass HuffmanTreeFactory<T extends Combinable<T>> {

 

    /**初始时一个list列表当作要编码的单元类的容器*/

    private List<HuffmanTree<T>> HuffmanTreeCollection;

   

//  public HuffmanTreeFactory(){}

    /**

     *@paramunitClasses待编码的单元类集合

     */

    public HuffmanTreeFactory(List<T> unitClasses){

       if(unitClasses == null || unitClasses.size() == 0)

           thrownew IllegalArgumentException("the unit classes collection can't be empty");

       HuffmanTreeCollection = new LinkedList<HuffmanTree<T>>();

       //初始化哈夫曼集合容器

       for(T unitClass : unitClasses){

           HuffmanTree<T> huffmanTree = new HuffmanTree<T>();

           huffmanTree.setRoot(unitClass);

           huffmanTree.setLeft(null);

           huffmanTree.setLeft(null);

           HuffmanTreeCollection.add(huffmanTree);

       }

       Collections.sort(HuffmanTreeCollection);

    }

    /**

     *将待编码的哈夫曼集合处理成只含有一个元素的集合,则这最后一个元素

     *即为最终生成的哈夫曼树

     */

    privatevoid generateHuffmanTree(){

       while(true){

           if(HuffmanTreeCollection == null || HuffmanTreeCollection.size() <= 1)

              break ;

           //处理之前一定要重新排序,这是哈夫曼编码的关键原理

           Collections.sort(HuffmanTreeCollection);

           HuffmanTree<T> huffmanTreeOne = HuffmanTreeCollection.remove(0);

           HuffmanTree<T> huffmanTreeTwo = HuffmanTreeCollection.remove(0);

           HuffmanTree<T> huffmanTreeNew = new HuffmanTree<T>();

           //将集合中前面两个元素合并成一个元素插到集合中去

           //并将第一个元素和第二个元素分别作为新元素的左,右节点

           huffmanTreeNew.setRoot(huffmanTreeOne.getRoot().combinate(huffmanTreeOne.getRoot(), huffmanTreeTwo.getRoot()));

           huffmanTreeNew.setLeft(huffmanTreeOne);

           huffmanTreeNew.setRight(huffmanTreeTwo);

           HuffmanTreeCollection.add(huffmanTreeNew);

       }

    }

   

    /**

     *

     *@return生成最终的哈夫曼树

     */

    public HuffmanTree<T> getHuffmanTree(){

       generateHuffmanTree();

       returnthis.HuffmanTreeCollection.get(0);

    }

   

}

 

========================================================================

/**

 *@(#)岑村高科

 */

package cn.javayy.struct;

 

import java.io.Serializable;

 

/**

 *自定义一个用于测试的单元类

 *@authorboss

 *

 *createon:下午09:53:072009-5-19

 */

publicclass UnitClass implements Serializable,Combinable<UnitClass>{

 

    /**

     *serialVersionUID

     */

    privatestaticfinallongserialVersionUID = -4109190579335512743L;

   

    /**出现概率数据*/

    privateintrate;

   

    public UnitClass(int rate){

       this.rate = rate;

    }

   

    publicint getRate() {

       returnrate;

    }

 

 

 

    publicvoid setRate(int rate) {

       this.rate = rate;

    }

 

 

 

    /**

     *implementsthidcompartTo()inordertosortthecollectionstoredfromunitclass

     */

    @Override

    publicint compareTo(UnitClass o) {

       return o.getRate() > this.rate ? 1: o.getRate() < this.rate ? -1 : 0;

    }

   

    @Override

    public String toString(){

       return"the rate is:" + rate;

    }

 

    /**

     *重写此方法用于哈夫曼编码时可以合并两个分支点信息

     */

    @Override

    public UnitClass combinate(UnitClass a, UnitClass b) {

       if(a == null || b == null)

           returnnull;

       returnnew UnitClass(a.getRate() + b.getRate());

    }

 

}

 

======================================================================

/**

 *@(#)岑村高科

 */

package cn.javayy.struct;

 

import java.util.ArrayList;

import java.util.List;

 

/**

 *@authorboss

 *

 *createon:下午10:03:122009-5-19

 */

publicclass Main {

 

   

    publicstaticvoid main(String[] args){

       List<UnitClass> l = new ArrayList<UnitClass>();

       l.add(new UnitClass(2));

       l.add(new UnitClass(4));

       l.add(new UnitClass(10));

       l.add(new UnitClass(7));

       l.add(new UnitClass(20));

       HuffmanTreeFactory<UnitClass> factory = new HuffmanTreeFactory<UnitClass>(l);

//     System.out.println(factory.getHuffmanTree());

       factory.getHuffmanTree().printHuffmanCoderString();

    }

}

 

===========================================================================

打印结果:

the the rate is:20 huffmanCoder:0
the the rate is:10 huffmanCoder:10
the the rate is:2 huffmanCoder:1100
the the rate is:4 huffmanCoder:1101
the the rate is:7 huffmanCoder:111

posted @ 2012-11-27 11:32  海鸟  阅读(583)  评论(0编辑  收藏  举报