二叉树之哈夫曼树

哈夫曼树(Huffman Tree)是一种用于数据压缩的树形结构,广泛应用于无损数据压缩算法中。由大卫·哈夫曼(David A. Huffman)在1952年提出。它主要用于构造哈夫曼编码,一种基于字符出现频率的变长编码方案。

压缩的目的是使用更少的空间来存储比较大的数据内容。这样首先就要对原数据中重复内容进行统计,重复最多的内容使用最短编码来表示。最短编码对应到树上可以使用节点路径来表示:从根节点到任意一个叶子节点的路径。

这样将重复多的项放于靠近根节点位置,重复最少的尽量存放于最底层叶子节点即可。每个节点位置确定可以根据重复次数作为权重来进行确定。

树的构建:

1、首先统计每个字符在待压缩数据中出现的频率作为节点权重值。

2、将每个字符及其频率(权重)作为叶子节点,构建一个优先队列。

3、从优先队列中取出两个最小权重的节点。创建一个新的内部节点,其权重为这两个节点权重的和,将这两个节点作为新节点的子节点。将新节点插入优先队列。重复上述步骤直到队列中只剩下一个节点,该节点就是哈夫曼树的根节点。

编码生成:

从根节点开始,进行遍历。通常左子节点标记为0,右子节点标记为1。这样可以为每个字符生成一个唯一的二进制编码

代码演示:

首先定义一个Node节点

    class Node<T> {
        T data;
        int weight;
        Node left;
        Node right;
        Node parent;

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

Node节点除了必要的引用关系,外还有一个额外必须的属性weight(权重)。

树的构建

    /**
     * 先按权重进行排序
     * 然后拿出两个最小的组成一个树,父节点为两个的权重和构造新节点,然后将这个节点再放入集合中
     * 再拿出两个最小的重复前面的动作,直到集合只有一个元素,则该元素为根元素
     * @param nodeList
     */
    void buildTree(List<Node> nodeList){
        if(nodeList.size() ==1) {
            root = nodeList.get(0);
            return;
        }

        while (nodeList.size() >1){
            nodeList = sort(nodeList);
            Node left = nodeList.remove(0);
            Node right = nodeList.remove(0);

            Node parent = new Node(null,left.weight + right.weight);
            parent.left = left;
            parent.right = right;
            left.parent = parent;
            right.parent = parent;
            nodeList.add(parent);
        }
        root = nodeList.get(0);
    }
    
    List<Node> sort(List<Node> nodeList){
        return nodeList.stream().sorted(Comparator.comparingInt(n -> n.weight)).collect(Collectors.toList());
    }

字符编码获取:

/**
     * 获取字符编码
     * 到左节点路径0,右节点路径为1
     * @param node
     * @return
     */
    String getCode(Node node){
        String code = "";
        Node tmp = node;
        while (tmp.parent != null){
            if(tmp.parent.left == tmp){
                code = "0" + code;
            }else{
                code = "1" + code;
            }
            tmp = tmp.parent;
        }
        return code;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值