Java 霍夫曼编码(Huffman Coding)

霍夫曼编码的具体步骤如下

1)将信源符号的概率按减小的顺序排队。

2)把两个最小的概率相加,并继续这一步骤,始终将较高的概率分支放在右边,直到最后变成概率1。

3)画出由概率1处到每个信源符号的路径,顺序记下沿路径的0和1,所得就是该符号的霍夫曼码字。   

4)将每对组合的左边一个指定为0,右边一个指定为1(或相反)
  1. 思路:一个节点类包括权重,父亲左儿子,右儿子节点,flag 的false表示已经使用过了,下次找两个最小的不会再找这个false掉的了,parentPath表示儿子到父亲的路径上的数字,左边为0,右边为1(我这个里面设置了左边儿子比右边儿子小),存储哈夫曼节点;然后一个list存储刚输入的码的权重生成的节点,每次查找flag为true的两个最小的权重的节点,生成父节点,设置相关节点的属性值;最后输出编码,不用遍历树,直接找到要编码的码,然后一路向上查找parentPath的值就是编码的倒序,故采用栈来保存,最后输出编码就是正确的编码格式。
  2. 话不多说,上代码:
package com.leibobo;

/**
 * Created by bobolei 18/4/13
 *哈夫曼节点定义
 */

public class NodeHuffman {

    //权重,标志位,父节点,左右儿子
    //flag = false表示还没有进行合并,即还是一个没有归类的节点
    //创建树的过程中直接标记哈夫曼编码,根节点父路劲为-1,其他父路径自己是左儿子,则为0,右儿子,则为1,后面直接找到要编码的数,向上查找即是哈夫曼编码的反路劲,翻转即可。。。哈哈哈哈,我号机智
    private int weight;
    private boolean flag; //默认false
    private int parentPath;  //默认是0
    public int getParentPath() {
        return parentPath;
    }

    public void setParentPath(int parentPath) {
        this.parentPath = parentPath;
    }

    private NodeHuffman parent,lChild,rChild;

    public NodeHuffman(){

    }

    public NodeHuffman(int weight){
        this.weight = weight;
        flag = true;
        parent = lChild = rChild = null;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public NodeHuffman getParent() {
        return parent;
    }

    public void setParent(NodeHuffman parent) {
        this.parent = parent;
    }

    public NodeHuffman getlChild() {
        return lChild;
    }

    public void setlChild(NodeHuffman lChild) {
        this.lChild = lChild;
    }

    public NodeHuffman getrChild() {
        return rChild;
    }

    public void setrChild(NodeHuffman rChild) {
        this.rChild = rChild;
    }


}
package com.leibobo;

import java.util.List;

/**
 * Created by bobolei 18/4/13
 *哈夫曼节点定义
 */

public class SelectTwoMin {
    //获取节点list中权重最小的两个,并返回,0,1大
        public NodeHuffman[] getMinTwo(List<NodeHuffman> listHuffman){
            NodeHuffman big = null;
            NodeHuffman small = null;

            for(int i = 0;i < listHuffman.size();i++){
                if(listHuffman.get(i).isFlag()){
                    if(small == null){
                        small = listHuffman.get(i);
                        continue;
                    }
                    if(small != null && big == null){
                        if(small.getWeight() > listHuffman.get(i).getWeight()){
                            big = small;
                            small = listHuffman.get(i);
                        }else{
                            big = listHuffman.get(i);
                        }
                        continue;
                    }
                    if(small != null && big != null){
                        if(listHuffman.get(i).getWeight() < big.getWeight() && listHuffman.get(i).getWeight() > small.getWeight()){
                            big = listHuffman.get(i);
                        }
                        if(listHuffman.get(i).getWeight() < small.getWeight()){
                            big = small;
                            small = listHuffman.get(i);
                        }
                    }
                }else{
                    continue;
                }
            }
            NodeHuffman[] minTwoHuffman = {small,big};
            return minTwoHuffman;       
        }
}
package com.leibobo;

import java.util.ArrayList;
import java.util.List;
/**
 * Created by bobolei 18/4/13
 *哈夫曼节点定义
 */

public class TreeHuffman {

    public List<NodeHuffman> getHuffmanTreeList(int[] weight,List<NodeHuffman> huffmanTreeList){
        int m=2*weight.length-1;
        //生成原始的Huffman节点
        for(int i = 0;i < weight.length;i++){
            NodeHuffman nodeHuffman = new NodeHuffman(weight[i]);
            huffmanTreeList.add(nodeHuffman);
        }

        SelectTwoMin selectTwoMin = new SelectTwoMin();
        for(int j = weight.length;j < m;j++){
            NodeHuffman[] minTwoHuffman = selectTwoMin.getMinTwo(huffmanTreeList);
            System.out.println("最小的两个:"+minTwoHuffman[0].getWeight()+"  "+minTwoHuffman[1].getWeight());
            minTwoHuffman[0].setFlag(false);
            minTwoHuffman[0].setParentPath(0);
            minTwoHuffman[1].setFlag(false);
            minTwoHuffman[1].setParentPath(1);

            NodeHuffman newNode = new NodeHuffman();
            newNode.setFlag(true);
            newNode.setlChild(minTwoHuffman[0]);
            newNode.setrChild(minTwoHuffman[1]);
            newNode.setWeight(minTwoHuffman[0].getWeight()+minTwoHuffman[1].getWeight());
            newNode.setParentPath(-1);
            newNode.setParent(null);

            huffmanTreeList.add(newNode);

            minTwoHuffman[0].setParent(huffmanTreeList.get(j));
            minTwoHuffman[1].setParent(huffmanTreeList.get(j));
        }
        return  huffmanTreeList;        
    }   
}
package com.leibobo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Stack;

/**
 * Created by bobolei 18/4/13
 *哈夫曼节点定义
 */
//java中方法传递的只是引用,不是对象,即一个对象通过方法操作返回的还是这个对象,只不过两个地方是不同的引用而已
public class Main {

    public static void main(String[] args) {

        // TODO Auto-generated method stub  

        Scanner sc=new Scanner(System.in);  
        System.out.println("输入编码的字符:");
        String code = sc.nextLine();
        System.out.println("请输入以此对应的次数:");
        String[] nums = null;   
        nums = sc.nextLine().split(" ");   
        int inputInt[]=new int[nums.length];  
        for(int i=0;i<inputInt.length;i++){  
            inputInt[i]=Integer.valueOf(nums[i]);  
        } 

        for(int j = 0;j < inputInt.length;j++){
            System.out.print(inputInt[j]+" ");
        }
        System.out.println(" ");

        //int[] inputInt={23,11,5,3,29,14,7,8};
        //int[] inputInt={12,6,2,18};
        System.out.println("输出:");
        Map<Integer,Stack<Integer>> map = new HashMap<Integer,Stack<Integer>>();
        List<NodeHuffman> huffmanTreeList = new ArrayList<NodeHuffman>();
        TreeHuffman treeHuffman = new TreeHuffman();
        treeHuffman.getHuffmanTreeList(inputInt, huffmanTreeList);

        for(int j = 0;j < inputInt.length;j++){
            boolean mark = true;
            Stack<Integer> stack = new Stack<Integer>();
            NodeHuffman node = huffmanTreeList.get(j);
            System.out.print("code:"+code.charAt(j)+" 权重:"+huffmanTreeList.get(j).getWeight() + "编码 :");
            while(mark){
                if(node.getParentPath() != -1){
                    System.out.print(node.getParentPath());
                    stack.push(node.getParentPath());
                    node = node.getParent();
                }else{
                    mark = false;
                }
            }
            System.out.println(" ");
            map.put(huffmanTreeList.get(j).getWeight(), stack);
        }
    }
}
阅读更多
个人分类: 杂论篇 Java
上一篇“==” 和equals()区别
下一篇@MappedSuperclass注解
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭