使用哈夫曼树实现哈夫曼编码的压缩

总体而言就是路径的统计那里我想了好久,还需要深刻理解递归的思想.

package HuffmanCode;


import java.util.*;

public class HuffmanCodeDemo01 {
    public static void main(String[] args) {
        String content = "i like like like java do you like a java";

        byte[] bytes = content.getBytes(); // 把String 中的每个字符取出


        List<Node> nodes = getNodes(bytes);
//        System.out.println(nodes);

//        System.out.println(bytes.length); //40个字节 也就320位

        Node tree = createTree(nodes);
        tree.pre();

    }

    // 接收一个字节数组,返回的就是一个List 里面有 Node["97",5]
    private static List<Node> getNodes(byte[] bytes) {
        // 先创建一个ArrayList
        ArrayList<Node> nodes = new ArrayList<>();

        HashMap<Byte, Integer> byteIntegerHashMap = new HashMap<>();
        // 存储每个byte 出现的次数 -> map<key ,value>
        for (byte b : bytes
        ) {
            Integer integer = byteIntegerHashMap.get(b); // 返回的是value值
            if (integer == null) {
                byteIntegerHashMap.put(b, 1);
            } else {
                byteIntegerHashMap.put(b, integer + 1);
            }

        }

        // 把每个键值对转成一个Node对象 然后加入到这个容器里面
        for (Map.Entry<Byte, Integer> entry : byteIntegerHashMap.entrySet()) {
            nodes.add(new Node(entry.getKey(), entry.getValue()));
        }


        return nodes;
    }


    // 通过一个list 创建一个赫夫曼树
    private  static  Node createTree(List<Node> nodes){
        while (nodes.size()>1){
            // 排序
            Collections.sort(nodes);

            // 取出前面两个树
          Node left = nodes.get(0);

            Node right = nodes.get(1);

            Node parent=new Node(left.weight+right.weight);

            parent.left=left;
            parent.right=right;

            nodes.add(parent);

            // 再连接上他们之间的关系


            // 再移除两个树
            nodes.remove(left);
            nodes.remove(right);
        }
        return   nodes.get(0); // 增加两个删除一个,到最后数组中只要一个root结点存在


    }


    static  Map<Byte,String> map=new HashMap<Byte, String>();


    static  StringBuilder stringBuilder=new StringBuilder();

    // 生成对应的赫夫曼编码表

    /**
     *
     * @param node
     * @param code 路径: 左子节点为0  右子节点为1
     * @param stringBuilder
     */
    private static  void getCodes(Node node,String code,StringBuilder stringBuilder){
        StringBuilder stringBuilder1 = new StringBuilder(stringBuilder);

        stringBuilder1.append(code);
        if (node!=null){ // 如果node ==null 不处理
                if(node.data==null){ // 非叶子节点
                    
                    getCodes(node.left,"0",stringBuilder1);
                    
                    getCodes(node.right,"1",stringBuilder1);
                }
                else {
                    map.put(node.data,stringBuilder1.toString());
                }
                
        }

    }




}


// Node 结点的信息
class Node implements Comparable<Node>

{
    Byte data; // 存放数据本身 ,根据AcsII码值存储

    int weight; // 获取权值,表示字符出现的次数

    Node left;

    Node right;

    Node(int weight){
        this.weight=weight;
    }

    Node(Byte data, int weight) {
        this.data = data;
        this.weight = weight;
    }


    @Override
    public int compareTo(Node o) {
        return this.weight - o.weight;
    }

    @Override
    public String toString() {
        return "Node{" +
                "data=" + data +
                ", weight=" + weight +
                '}';
    }

    // 前序遍历
    public void pre() {
        System.out.println(this);
        if (this.left != null) {
            this.left.pre();
        }
        if (this.right != null) {
            this.right.pre();
        }
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值