哈夫曼树(Huffman)

news2024/11/16 19:46:22

哈夫曼树

Huffman 编码问题

问题引入

什么是编码?

简单说就是建立【字符】到【数字】的对应关系,如下面大家熟知的 ASC II 编码表,例如,可以查表得知字符【a】对应的数字是十六进制数【0x61】

\000102030405060708090a0b0c0d0e0f
0000000102030405060708090a0b0c0d0e0f
0010101112131415161718191a1b1c1d1e1f
002020!"#$%&()*+,-./
00300123456789:;<=>?
0040@ABCDEFGHIJKLMNO
0050PQRSTUVWXYZ[\]^_
0060`abcdefghijklmno
0070pqrstuvwxyz{|}~7f

注:一些直接以十六进制数字标识的是那些不可打印字符

传输时的编码

  • java 中每个 char 对应的数字会占用固定长度 2 个字节
  • 如果在传输中仍采用上述规则,传递 abbccccccc 这 10 个字符
    • 实际的字节为 0061006200620063006300630063006300630063(16进制表示)
    • 总共 20 个字节,不经济

现在希望找到一种最节省字节的传输方式,怎么办?

假设传输的字符中只包含 a,b,c 这 3 个字符,有同学重新设计一张二进制编码表,见下图

  • 0 表示 a
  • 1 表示 b
  • 10 表示 c

现在还是传递 abbccccccc 这 10 个字符

  • 实际的字节为 01110101010101010 (二进制表示)
  • 总共需要 17 bits,也就是 2 个字节多一点,行不行?

不行,因为解码会出现问题,因为 10 会被错误的解码成 ba,而不是 c

  • 解码后结果为 abbbababababababa,是错误的

怎么解决?必须保证编码后的二进制数字,要能区分它们的前缀(prefix-free)

用满二叉树结构编码,可以确保前缀不重复

请添加图片描述

  • 向左走 0,向右走 1
  • 走到叶子字符,累计起来的 0 和 1 就是该字符的二进制编码

再来试一遍

  • a 的编码 0
  • b 的编码 10
  • c 的编码 11

现在还是传递 abbccccccc 这 10 个字符

  • 实际的字节为 0101011111111111111(二进制表示)
  • 总共需要 19 bits,也是 2 个字节多一点,并且解码没有问题了,行不行?

这回解码没问题了,但并非最少字节,因为 c 的出现频率高(7 次)a 的出现频率低(1 次),因此出现频率高的字符编码成短数字更经济

考察下面的树

请添加图片描述

  • 00 表示 a
  • 01 表示 b
  • 1 表示 c

现在还是传递 abbccccccc 这 10 个字符

  • 实际的字节为 000101 1111111 (二进制表示)
  • 总共需要 13 bits,这棵树就称之为 Huffman 树
  • 根据 Huffman 树对字符和数字进行编解码,就是 Huffman 编解码

Huffman 树

public class HuffmanTree {

    Node root;
    String code;
    private static class Node{
        char ch;
        int freq;
        String code;
        Node left;
        Node right;

        public Node(char ch) {
            this.ch = ch;
        }

        public Node(char ch, int freq) {
            this.ch = ch;
            this.freq = freq;
        }

        public Node(int freq, Node left, Node right) {
            this.freq = freq;
            this.left = left;
            this.right = right;
        }

        public boolean isLeaf(){
            return this.left == null && this.right == null;
        }
    }

    public HuffmanTree(String s){
        char[] charArray = s.toCharArray();
        Map<String,Integer> map = new HashMap();
        for (char c : charArray) {
            Integer i = map.getOrDefault(String.valueOf(c),0);
            map.put(String.valueOf(c),i+1);
        }
        PriorityQueue<Node> queue = new PriorityQueue<>(Comparator.comparingInt(v -> v.freq));
        for (String string : map.keySet()) {
            Node node = new Node(string.charAt(0), map.get(string));
            queue.add(node);
        }
        while(queue.size() > 1){
            Node n1 = queue.poll();
            Node n2 = queue.poll();
            Node node = new Node(n1.freq + n2.freq, n1, n2);
            queue.add(node);
        }
        root = queue.peek();
        s = doEncode(root,new StringBuilder(),s);
        code = s;
    }
}

Huffman 编解码

补充两个方法,注意为了简单期间用了编解码都用字符串演示,实际应该按 bits 编解码

public class HuffmanTree {
    // ...

    // 编码
    private String doEncode(Node node,StringBuilder sb,String s){
        if(!node.isLeaf()){
            s = doEncode(node.left,sb.append(0),s);
            sb.deleteCharAt(sb.length()-1);
            s = doEncode(node.right,sb.append(1),s);
            sb.deleteCharAt(sb.length()-1);
        }else{
            node.code = sb.toString();
            while(s.contains(String.valueOf(node.ch))){
                s = s.replace(String.valueOf(node.ch), node.code);
            }
        }
        return s;
    }

    public String encode(){
        return code;
    }

    public String decode(String code){
        Node node = root;
        StringBuilder sb = new StringBuilder();
        char[] charArray = code.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            if(charArray[i] == '0'){
                node = node.left;
            }else {
                node = node.right;
            }
            if(node.isLeaf()){
                sb.append(node.ch);
                node = root;
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        HuffmanTree tree = new HuffmanTree("aabcccccc");
        String encode = tree.encode();
        System.out.println(encode);
        String decode = tree.decode(encode);
        System.out.println(decode);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1409733.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

五款焊在电脑上的效率软件

在当今快节奏的商业环境中&#xff0c;提高工作效率成为了每个人都渴望实现的目标。尤其是在面对繁忙的工作日程、庞杂的任务清单和团队合作的压力时&#xff0c;我们需要一些可靠的工具来帮助我们更好地管理时间、组织工作和提高生产力。幸运的是&#xff0c;现在有许多高效的…

k8s的图形化工具--rancher

什么是rancher&#xff1f; rancher是一个开源的企业级多集群的k8s管理平台 rancher和k8s的区别 都是为了容器的调度和编排系统&#xff0c;但是rancher不仅能够调度&#xff0c;还能管理k8s集群&#xff0c;自带监控&#xff08;普罗米修斯&#xff09; 实验部署 实验架构…

分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别

分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别 目录 分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 …

WinSCP如何使用公网TCP地址访问本地服务器

文章目录 1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件&#xff0c;它的主要功能是在本地与远程计…

基于 Gurobi 的纸浆运载船顺序装卸决策建模求解|Gurobi优化应用

Pulp-Carrier-Loading-Optimization-with-Gurobi 基于 Gurobi 的纸浆运载船顺序装卸决策建模求解。中山大学智能工程学院《运筹学》课程期末建模课程设计。优化工具&#xff1a;Python的Gurobi 项目仓库 Github: Pulp-Carrier-Loading-Optimization-with-Gurobi 摘要 本研究…

信驰达科技多款TI CC2340R5系列低功耗蓝牙模块强势上线

信驰达科技基于TI CC2340R5推出了多款蓝牙串口模块&#xff0c;包括RF-BM-2340B1、RF-BM-2340B1I、RF-BM-2340A2、RF-BM-2340A2I、RF-BM-2340C2&#xff0c;RF-BM-2340x系列低功耗蓝牙模块采用TI CC2340R5 5 mm x 5 mm(VQFN40) 和4 mm x 4 mm(VQFN24)封装SoC&#xff0c;支持板…

信息检索与数据挖掘 | (十二)聚类

文章目录 &#x1f4da;聚类&#x1f4da;KMeans&#x1f4da;层次聚类&#x1f407;层次聚类概述&#x1f407;dendrogram-树状图&#x1f407;linkages-衡量两个类之间的距离&#x1f407;Lance-Williams算法&#x1f407;K-means VS 层次聚类 &#x1f4da;DBSCAN &#x1f…

pdf怎么转换成jpg图片?pdf转图片工具用它就够了

有时候&#xff0c;我们可能需要将pdf文档转换为图片格式&#xff0c;以便于文档的处理和管理。通过将pdf转换为图片&#xff0c;可以将每一页pdf转换为独立的图片文件&#xff0c;便于整理、存储和管理&#xff0c;如果您有多个PDF文件需要转换成图片&#xff0c;可以批量pdf转…

WorkPlus AI智能客服解决方案,提升企业服务质量

在当今竞争激烈的商业环境中&#xff0c;提供卓越的客户服务成为企业赢得市场竞争的关键。而AI智能客服技术的不断发展&#xff0c;则成为了提高服务效率和满意度的利器。作为一款领先的AI助理解决方案&#xff0c;WorkPlus AI助理以其出色的性能和智能化的功能&#xff0c;助力…

(二十八)ATP应用测试平台——使用electron集成vue3桌面应用程序

前言 Electron 是一个开源的框架&#xff0c;它允许使用 Web 技术&#xff08;HTML、CSS 和 JavaScript&#xff09;构建跨平台的桌面应用程序。通过 Electron&#xff0c;开发者可以使用前端技术栈来创建具有原生应用程序体验的桌面应用。 Electron可以在 Windows、Mac 和 L…

【C++进阶】STL容器--list使用迭代器问题分析

目录 前言 1. list的基本使用 1.1 list构造函数 1.2 list迭代器 1.3 list capacity 1.4 list元素访问 1.5 list 修改操作 insert erase swap resize clear 2. list失效迭代器问题 3. list使用算法库函数问题 总结 前言 list&#xff08;链表&#xff09;在C中非常重要…

怎么把音频转换成二维码?把音频制作成二维码的方法

现在很多二维码被用来作为信息传递的一种方式&#xff0c;常见的类型包括文本、图片、音视频等等。选择这种方式的好处在于&#xff0c;不仅制作起来非常简单&#xff0c;有效的降低成本&#xff0c;而且便捷性也比较强。那么如何将音频格式的文件做成二维码图片呢&#xff1f;…

一文读懂:怎样将 MongoDB 转变为预测数据库?操作详解来了!

商界对人工智能 (AI) 和机器学习 (ML) 的兴趣日益浓厚。ML/AI 的预测功能能够以比人工分析更快的速度从检测到的模式中快速获得见解。此外&#xff0c;生成式机器学习应用程序&#xff08;如 OpenAI 和 Hugging Face&#xff09;的最新进展为企业提供了强大工具以用于生成和分析…

arcgis 面要素shp数据处理

面要素是工作中用到最多的&#xff0c;那么面要素是如何形成的呢&#xff0c;主要还是由闭合的线要素转换而成。在面要素数据中常用的有以下几点&#xff1a; 一、 线转面&#xff08;要素转面&#xff09; 通过上一篇得到了点转线的要素&#xff0c;那么根据上节的线要素&am…

【Linux C | 进程】Linux 进程间通信的10种方式(2)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

jieba.net使用NuGet管理器安装后初始化TfidfExtractor对象时报错

在引用安装jieba.net后,引用的Resources下只有如图几个文件 导致初始化TfidfExtractor时报错,报找不到 Could not find file E:\\TZKJNet\\robotindustry\\modules\\Tzkj.Superhard.SupplyDemand\\src\\Tzkj.Superhard.SupplyDemand.HttpApi.Host\\bin\\Debug\\net7.0\\Reso…

【C++干货基地】C++入门篇:输入输出流 | 缺省函数 | 函数重载(文末送书)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

[leetcode] 18. 四数之和

文章目录 题目描述解题方法排序 双指针java代码 相似题目 题目描述 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一对应&a…

《解锁R统计分析:深度探索R Commander图形界面》

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在数据科学与大数据技术的浪潮中&#xff0c;R…

Python爬取猫眼电影专业评分数据中的应用案例

在数据分析和可视化展示中&#xff0c;获取准确的电影专业评分数据至关重要。猫眼电影作为中国领先的电影信息与票务平台&#xff0c;其专业评分对于电影行业和影迷的数据来说具有重要意义。通过Python爬虫技术&#xff0c;我们可以实现从猫眼电影网站上自动获取这些数据目标。…