哈夫曼树和哈夫曼编码

哈夫曼树

假设有N个结点,现在我们需要把这N个结点弄成一棵树,当然了并不是随随便便的一棵树,构造这棵树的要求是:第一:这N个结点必须是这棵树的叶子结点(即没有孩子结点的结点),第二:在这N个结点中 值大的的结点在上面,值小的的结点在下面。第三:因为要连接叶子结点,所以肯定需要创建新的结点,该新的结点就作为叶子结点的父结点,该父结点的值就是两个子结点和的值。
例子:在这里插入图片描述
哈夫曼树
在这里插入图片描述

/*
1、先将珠宝们从小到大排序
2、找出最小的两个
3、将这两个融合起来,提炼成一颗价值叠加的玛瑙珠宝
4、重复执行以上步骤,将会提炼一颗终极珠宝-----宝格丽珠宝
 */
public class HuffmanTree {
    public static void main(String[] args) {
        huffmanTree();
    }

    public static void huffmanTree(){
        jewelry jewelry1 = new jewelry(13);
        jewelry jewelry2 = new jewelry(7);
        jewelry jewelry3 = new jewelry(8);
        jewelry jewelry4 = new jewelry(3);
        jewelry jewelry5 = new jewelry(29);
        jewelry jewelry6 = new jewelry(6);
        jewelry jewelry7 = new jewelry(1);
        List<jewelry> list = new ArrayList<jewelry>();
        list.add(jewelry1);
        list.add(jewelry2);
        list.add(jewelry3);
        list.add(jewelry4);
        list.add(jewelry5);
        list.add(jewelry6);
        list.add(jewelry7);

        while (list.size() > 1) {
            //排序
            Collections.sort(list);

            //获取最小的两个
            jewelry jewelryLeft = list.get(0);
            jewelry jewelryRight = list.get(1);

            //融合成玛瑙珠宝
            jewelry root = new jewelry(jewelryLeft.value + jewelryRight.value);
            root.leftJewelry = jewelryLeft;
            root.rightJewelry = jewelryRight;

            //去除掉原来最小的两颗珠宝
            list.remove(jewelryLeft);
            list.remove(jewelryRight);

            //把玛瑙塞进去
            list.add(root);
        }
        
        // 前序遍历查看
        jewelry.traversal(list.get(0));
    }
}


//想用Collections.sort()排序  该接口必须要实现
class jewelry implements Comparable<jewelry>{
    jewelry leftJewelry;
    jewelry rightJewelry;
    int value;
    public jewelry(int value){
        this.value = value;
    }

    @Override
    public String toString() {
        return "jewelry{" +
                "value=" + value +
                '}';
    }

    @Override
    public int compareTo(jewelry o) {
        //从小到大排序,因为如果返回的是负数,说明o比this小,那么就把o放在this前面
        return this.value - o.value;
    }

    //前序遍历查看 有没有写错
    public static void traversal(jewelry root){
        System.out.println(root);
        if (root.leftJewelry != null)
            traversal(root.leftJewelry);
        if (root.rightJewelry != null)
            traversal(root.rightJewelry);
    }
}

通过上面的哈夫曼树,我们就可以对每个结点进行编码了;
即:规定从左边走0,从右边走为1,
在这里插入图片描述
这样 12的编码就是:001;3:0000;56: 1;10: 0001; 32: 01;
同时我们可以发现:任意一个数字的编码 都不是其他数字编码的前缀,这个特点尤其重要,因为可以避免混淆;
举一个反例: 假设 数字3的编码为:001 ;数字5的编码为:0010, 那么当读取当001的时候我们不知道是否读到这里就停止,还是继续读下去,这样就会造成问题;而哈夫曼编码就避免了这个问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值