【数据结构与算法】哈夫曼树与哈夫曼编码

文章目录

  • 哈夫曼树(最优二叉树)
    • 定义
      • 举个🌰(WPL的计算)
    • 哈夫曼树的构造(最优二叉树的构造)
      • 举个🌰
    • 哈夫曼树的性质
  • 哈夫曼编码
    • 定义
    • 构造


哈夫曼树(最优二叉树)

在介绍哈夫曼树之前,我们需要介绍一些概念:

  • 路径:路径是指从一个结点到另一个结点的之间所经过的所有结点构成的序列。

  • 路径长度:路径长度是路径上所经过的边的个数

  • :在应用树的时候,我们常常会将树的结点赋予一个表示某种意义的数值,这个值称为权。

  • 结点的带权路径长度:从根结点到一个结点的路径长度 * 该结点的权值 = 该结点的带权路径长度。

  • 树的带权路径长度(WPL):树中所有叶结点的带权路径长度之和称为树的带权路径长度

定义

在含有n个带权叶结点的二叉树中,其中带权路径最小的二叉树称为哈夫曼树,也称最优二叉树

举个🌰(WPL的计算)

在这里插入图片描述

第一棵树的 W P L = 7 ∗ 2 + 5 ∗ 2 + 2 ∗ 2 + 4 ∗ 2 = 36 WPL=7*2+5*2+2*2+4*2=36 WPL=72+52+22+42=36

第二棵树的 W P L = 4 ∗ 2 + 7 ∗ 3 + 5 ∗ 3 + 2 ∗ 1 = 46 WPL=4*2+7*3+5*3+2*1=46 WPL=42+73+53+21=46

第三棵树的 W P L = 7 ∗ 1 + 5 ∗ 2 + 2 ∗ 3 + 4 ∗ 3 = 35 WPL=7*1+5*2+2*3+4*3=35 WPL=71+52+23+43=35

第三颗树的 WPL 恰好是所有含有n个带权叶结点的二叉树中最小的,因此第三棵树为哈夫曼树。

注意:证明一个树是否为哈夫曼树,要看的是所有含有n个带权叶结点的WPL,而不是给几个二叉树选其中WPL最小的。(当然,由于这种证明几乎不可能实现,所以要证明一棵树为哈夫曼树,我们只需要证明它的结构符合最优构造方法即可——因为哈夫曼树并不唯一,例如把一颗哈夫曼树的左右子树交换,它就构成了一棵新的哈夫曼树)。

哈夫曼树的构造(最优二叉树的构造)

给定 n n n 个权值分别为 w 1 , w 2 , . . . , w n w_1,w_2,...,w_n w1,w2,...,wn 的结点,构造最优二叉树的方法如下:

  1. 将这 n n n 个结点视为 n n n 棵只有一个结点的二叉树,它们构成了一个森林 F F F
  2. 在森林中选择两颗根节点权值最小的二叉树 T 1 , T 2 T_1,T_2 T1,T2,新增一个结点 N N N,把 T 1 , T 2 T_1,T_2 T1,T2 的根节点作为 N N N 的左、右孩子构成一棵新的二叉树 T 3 T_3 T3 N N N的权值等于 T 1 , T 2 T_1,T_2 T1,T2的根的权值之和。
  3. F F F 中删除 T 1 , T 2 T_1,T_2 T1,T2,把 T 3 T_3 T3加入到 F F F 中。
  4. 重复步骤 2 , 3 2,3 2,3,直到 F F F 中只剩下一颗树。

如果对哈夫曼树的构造方法的正确性感兴趣的同学,可以搜一搜哈夫曼树的构造方法的正确性证明。

举个🌰

在这里插入图片描述

把这几个叶结点按权值的从小到大排列,有:

在这里插入图片描述

选择权值最小的两个结点构成新的二叉树,有:

在这里插入图片描述

继续选择两个最小的结点,有:

在这里插入图片描述

继续:

在这里插入图片描述
这样我们就得到一颗哈夫曼树了

哈夫曼树的性质

  1. 初始结点最终都为叶结点,并且权值越小的结点到根节点的路径长度越大。
  2. 因此哈夫曼树的结点总数为 2 ∗ n − 1 2*n-1 2n1,因为构造的过程中新增了n-1个结点(即新增了n-1个分支结点)。
  3. 哈弗曼树中不存在度为1的结点,因为每次构造都是选择两颗树作为新结点的子节点。
  4. 哈夫曼树的带权路径长度,等于所有分支结点的权值之和。

哈夫曼编码

在了解哈夫曼编码前,我们先了解一些相关的概念:

  • 定长编码:长度固定的编码。
  • 变长编码:长度不固定的编码。
  • 前缀编码:没有一个编码是另一个编码的前缀,这样的编码叫做前缀编码(显然,根据定义来说,定长编码一定是前缀编码,变长编码不一定是前缀编码)。

对于前缀编码来说,我们可以用树辅助构造前缀编码。

例如:假设要为a,b,c,d四个字符设计二进制前缀编码,那么我们可以用二叉树来辅助构造。

为了使编码能够符合前缀编码的要求,显然,a、b、c、d不会出现在分支结点上。

我们设从任意结点往左边走代表0,从任意结点往右边走代表1,(即指向左子树的边代表0,指向右子树的边代表1)那么a、b、c、d的编码为从根节点到对应叶结点所经过的边代表的值的序列。

我们可以得到如下所示的二叉树:

在这里插入图片描述

  • a的编码为:0
  • b的编码为:10
  • c的编码为:110
  • d的编码为:111

显然,没有一个编码是另一个编码的前缀,这种编码是前缀编码。

定义

哈夫曼编码是一种变长的二进制前缀编码,它利用哈夫曼树来辅助构造编码,能够非常有效地压缩二进制数据。

构造

我们将每一个字符当做一个独立的结点,其权值等于它出现的次数(或频度),构造一棵哈夫曼树。

设从任意结点指向左子树的边代表0,指向右子树的边代表1指向左子树的边表示1,指向右子树的边表示0。则各个结点的编码为从根节点到对应结点所经过的边代表的值的序列。

上面的例子就是一个构造哈夫曼编码的案例。

注意:相同结点构造出的哈夫曼树并不唯一,因为它并没有限制到底是左大右小还是右大左小。但相同结点构造出的不同的哈夫曼树的WPL一定是相同的。

同理,哈夫曼编码也是不唯一的。

全篇至此结束,感谢观看。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SD3开源:AI绘画的新纪元,出图效果巨好,不容错过!(附教程)

大家好,我是画画的小强。 这两天,Stability AI 将史上最牛的AI绘画模型SD3开源了,真是有格局! 虽说只是中杯的20亿参数版本,但我已经很满足了,再高的版本,我这普通的16G 4070Ti Super 显卡也跑…

【Java】类与类的关系及其总结

类和类的关系 代码 总结: 【1】面向对象的思维:找参与者,找女孩类,找男孩类 【2】体会了什么叫方法的性擦,什么叫方法的实参: 具体传入的内容 实参: 【3】类和类可以产生关系: …

IIC通信总线

文章目录 1. IIC总线协议1. IIC简介2. IIC时序1. 数据有效性2. 起始信号和终止信号3. 数据格式4. 应答和非应答信号5. 时钟同步6. 写数据和读数据 2. AT24C023. AT24C02读写时序4. AT24C02配置步骤5. 代码部分1. IIC基本信号2. AT24C02驱动代码3. 实验结果分析 1. IIC总线协议 …

上位机图像处理和嵌入式模块部署(h750和市场上的开发板)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 目前在电商网站上面,关于h750的开发板很多。一种是某原子和某火出品的板子,这一类的板子就是做的比较大,功能比…

【python-AI篇】人工智能技能树思维导图

大致总结一下得出如下思维导图,如不完善日后迭代更新 1. python基础三方库 1.1 科学计算库 ---- numpy库 1.2 科学计算库 ---- Scipy库 1.3 数据分析处理库 ---- pandas库 1.4 可视化库 ---- matplotlib库 1.5 可视化库 ---- seaborn库 1.6 机器学习和数据挖掘库 …

定个小目标之刷LeetCode热题(20)

这题与上一题有一点不同,上一题是判断链表是否存在环,这题是寻找入环的第一个节点,有一个规则是这样的,在存在环的情况下,运用快慢指针判断是否有环结束时,把快指针指向头结点,慢指针不变&#…

【TB作品】MSP430 G2553 单片机 口袋板 日历 时钟 闹钟 万年历 电子时钟 秒表显示

文章目录 功能介绍操作方法部分流程图代码录制了一个演示视频可以下载观看 功能介绍 时间与日期显示: 实时显示当前时间(小时、分钟、秒)和日期(年、月、日)。 闹钟功能: 设置闹钟时间(小时、分…

仿FC数学金刚游戏介绍

简介 Math Monkey是Simple2l工作室开发的第二款小游戏,灵感来源于FC游戏平台的数学金刚游戏。小学时玩FC游戏是业余时间最期待的事情,还记得有一次和玩伴玩游戏时已经晚上了,于是约定再玩一把就各回各家,没想到又连玩了N把每一把…

12.容器间的互联(--link 是单方向的!!!)

容器间的互联(–link 是单方向的!!!) –link意思就是链接容器进行通信 用法:--link 容器名字:随意设置别名;例如:--link nginx:nginx 注释:同一个容器中,可…

mysql报错Access denied for user ‘root‘,navicat可以连接mysql,spring不能连mysql

首先修改配置文件跳过验证,编辑你自己挂载的配置文件的位置 #查找my.cnf位置 sudo find / -name "my.cnf"编辑mysql配置文件 vim /opt/soft/mysql/conf/my.cnf #在[mysqld]下面添加 skip_grant_tables#重启mysql docker restart mysql#进入容器 docke…

【ARMv8/ARMv9 硬件加速系列 3.2 -- SVE 读写内存指令 st1b | st1w | st1w | st1d 使用介绍】

文章目录 SVE Load 和 Store 指令使用介绍LD1 加载指令ST1 存储指令PFR 预取指令参考示例LD1 加载示例ST1 存储示例代码实例SVE Load 和 Store 指令使用介绍 ARMv9架构中的SVE(Scalable Vector Extension)指令集为向量计算提供了强大支持,特别是针对不同数据类型和访问模式…

计算机游戏因为d3dcompiler_47.dll丢失无法启动怎么办?解决只要d3dcompiler_47.dll丢失无法启动游戏软件的方法

d3dcompiler_47.dll 是一个动态链接库文件,属于 Microsoft DirectX 的一部分,主要负责编译和运行 3D 图形程序。它是支持 Direct3D 功能的核心组件,Direct3D 是一种用于编程 3D 图形的 API,广泛应用于游戏和图形密集型应用程序中。…

面试官考我Object类中的所有方法及场景使用?我...

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java 知识点啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯&a…

CV预测:快速使用ResNet深度残差神经网络并创建自己的训练集

AI预测相关目录 AI预测流程,包括ETL、算法策略、算法模型、模型评估、可视化等相关内容 最好有基础的python算法预测经验 EEMD策略及踩坑VMD-CNN-LSTM时序预测对双向LSTM等模型添加自注意力机制K折叠交叉验证optuna超参数优化框架多任务学习-模型融合策略Transform…

基于BERT微调+模板填充快速实现文本转DSL查询语句

前言 Text2SQL是指将自然语言转化为类SQL查询语句,使得用户的查询文本可以直接实现和数据库交互,本文介绍一种以BERT为基础模型,通过模板填充来实现的Text2SQL算法和产品化。 内容摘要 Text2SQL任务说明模板填充的思路条件列选择子模型搭建…

深度搜索(递归实现)-计算岛屿最大面积

一、问题描述 二、解题思路 该题目采用递归方法:如果当前是“岛屿”,那么计算上下左右四个方向的面积值1作为当前岛屿总面积返回。 三、代码实现 import java.util.*;public class Solution {int maxArea0;/*** 代码中的类名、方法名、参数名已经指定&…

文章MSM_metagenomics(三):Alpha多样性分析

欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2 介绍 本教程使用基于R的函数来估计微生物群落的香农指数和丰富度,使用MetaPhlAn prof…

【UIDynamic-动力学-UIGravityBehavior-重力行为 Objective-C语言】

一、UIGravityBehavior,重力行为, 1.接下来啊,我们一个一个来做, 新建一个项目,叫做:01-重力, 接下来,我们在这个ViewController里边, ViewDidLoad:里边,先写一段简单的代码, 我们写这么一段简单的代码,新建一个红色的UIView,把它显示在屏幕上, UIView *redVie…

03-RAG的核心 -结果召回和重排序

1 完整RAG应用的检索流程 2 Query预处理 2.1 意图识别 判断query问的是什么类型的问题,从而决定是否走RAG链路。 示例1: 深圳有什么好玩的 闲聊问题VDB支持哪些检索算法 产品常见问题 示例2: 为什么某个MongoDB实例内存占用过高 检查类…

博科SAN交换机初始化和Zone创建

1 初始化 博科的SAN交换机默认配置: 地址:10.77.77.77 账户:admin 密码:password 设备硬件查看 ***-SAN-1:admin> chassisshowFAN Unit: 1 Fan Direction: Reverse (Non-portside Intake) Time Awake: 0 daysP…