用java实现哈夫曼编码过程


       今天在信息论课上听到了哈夫曼编码,想起当初在数据结构中也学到过,于是脑子一热,想编程实现它,于是花了几个小时的时间将它编了出来,希望能为大家带来一点点帮助。在编的过程中只求实现功能,不求性能最优,所以难免存在冗余的地方。
       程序共包含两个java源文件:HuffmanCoding.javaNode.java,分别如下:

HuffmanCoding.java :
import java.util.ArrayList;
import java.util.List;

/**
 * Created by LiK on 2016/12/12.
 */
public class HuffmanCoding {
    public static final Double[] probability = new Double[]{0.2,0.19,0.18,0.17,0.16,0.08,0.02};

    public static void main(String[] args) {
        getHuffmanCode(probability);
    }

    /**
     * 由概率得哈夫曼编码
     * @param probab
     * @return
     */
    public static String[] getHuffmanCode(Double[] probab) {
        int publicIndex = 0;

        //probab从小到大排序
        probab = sort(probab);

        List<Node> list = new ArrayList<Node>();
        List<Node> allList = new ArrayList<Node>();
        for(Double p : probab) {
            Node node = new Node();
            node.setIndex(publicIndex++);       //设置脚标
            node.setProbability(p);             //设置概率
            allList.add(node);
            list.add(node);
        }

        while(list.size() > 1) {
            //1.排 序
            list = sortList(list);

            //2.取最小的两个,设置编码
            Node nodeL = list.get(0);
            Node nodeR = list.get(1);
            for(int i = 0; i < allList.size(); i++) {
                if(nodeL.getIndex() == allList.get(i).getIndex()) {
                    allList.get(i).setCode("0");
                    break;
                }
            }
            for(int i = 0; i < allList.size(); i++) {
                if(nodeR.getIndex() == allList.get(i).getIndex()) {
                    allList.get(i).setCode("1");
                    break;
                }
            }

            //3.增父节点
            Node parentNode = new Node();
            parentNode.setParentFlag(true);
            parentNode.setIndex(publicIndex++);
            parentNode.setProbability(nodeL.getProbability() + nodeR.getProbability());
            parentNode.setSonIndex1(nodeL.getIndex());
            parentNode.setSonIndex2(nodeR.getIndex());
            list.add(parentNode);
            allList.add(parentNode);

            //4.减子节点,
            list.remove(0);
            list.remove(0);

        }

        //逆向确定完整编码
        reverseSearch(allList, allList.size() - 1);

        //输出前probab.length个元素
        String[] strings = new String[probab.length];
        for(int i = 0; i < probab.length; i++) {
            System.out.println(allList.get(i).getProbability() + ": " + allList.get(i).getCode());
            strings[i]= allList.get(i).getProbability() + ": " + allList.get(i).getCode();
        }



        return strings;
    }

    /**
     * 逆向确定编码
     * @param allList
     * @param index
     */
    public static void reverseSearch(List<Node> allList, int index) {
        Node node = allList.get(index);
        if(node.isParentFlag()) {
            String code1 = allList.get(node.getSonIndex1()).getCode();
            String code2 = allList.get(node.getSonIndex2()).getCode();
            allList.get(node.getSonIndex1()).setCode(node.getCode() + "" + code1);
            allList.get(node.getSonIndex2()).setCode(node.getCode() + "" + code2);
            reverseSearch(allList, node.getSonIndex1());
            reverseSearch(allList, node.getSonIndex2());
        }
    }

    /**
     * 在List中进行冒泡排序
     * @param list
     * @return
     */
    public static List<Node> sortList(List<Node> list) {
        for(int i = 0; i < list.size(); i++) {
            for(int j = 0; j < list.size() - i - 1; j++) {
                if(list.get(j).getProbability() > list.get(j + 1).getProbability()) {
                    Node temp = list.get(j);
                    list.set(j, list.get(j + 1));
                    list.set(j + 1, temp);
                }
            }
        }

        return list;
    }

    /**
     * 冒泡排序
     * @param probab
     * @return
     */
    public static Double[] sort(Double[] probab) {
        for(int i = 0; i < probab.length; i++) {
            for(int j = 0; j < probab.length - i - 1; j++) {
                if(probab[j] > probab[j + 1]) {
                    Double temp = probab[j];
                    probab[j] = probab[j + 1];
                    probab[j + 1] = temp;
                }
            }
        }

        return probab;
    }
}

Node.java :
/**
 * Created by LiK on 2016/12/12.
 */
public class Node {
    Integer index;
    Double probability;
    String code = "";
    boolean parentFlag = false;
    Integer sonIndex1;
    Integer sonIndex2;

    public Node() {

    }

    public Integer getIndex() {
        return index;
    }

    public void setIndex(Integer index) {
        this.index = index;
    }

    public Double getProbability() {
        return probability;
    }

    public void setProbability(Double probability) {
        this.probability = probability;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public boolean isParentFlag() {
        return parentFlag;
    }

    public void setParentFlag(boolean parentFlag) {
        this.parentFlag = parentFlag;
    }

    public Integer getSonIndex1() {
        return sonIndex1;
    }

    public void setSonIndex1(Integer sonIndex1) {
        this.sonIndex1 = sonIndex1;
    }

    public Integer getSonIndex2() {
        return sonIndex2;
    }

    public void setSonIndex2(Integer sonIndex2) {
        this.sonIndex2 = sonIndex2;
    }
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值