哈夫曼树以及哈夫曼编码的构造步骤

2023-10-30

注意:哈夫曼树并不唯一,但带权路径长度一定是相同的。

第一部分;由给定结点构造哈夫曼树

(1)8个结点的权值大小如下:


(2)从19,21,2,3,6,7,10,32中选择两个权小结点。选中2,3。同时算出这两个结点的和5。


(3)从19,21,6,7,10,32,5中选出两个权小结点。选中5,6。同时计算出它们的和11。


(4)从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。
(BTW:这时选出的两个数字都不是已经构造好的二叉树里面的结点,所以要另外开一棵二叉树;或者说,如果两个数的和正好是下一步的两个最小数的其中的一个,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生
长。)


(5)从19,21,32,11,17中选出两个权小结点。选中11,17。同时计算出它们的和28。


(6)从19,21,32,28中选出两个权小结点。选中19,21。同时计算出它们的和40。另起一颗二叉树。


(7)从32,28, 40中选出两个权小结点。选中28,32。同时计算出它们的和60。  


(8)从 40, 60中选出两个权小结点。选中40,60。同时计算出它们的和100。 好了,此时哈夫曼树已经构建好了。



第二部分:由上述所得哈夫曼树写出哈夫曼编码

首先我们来看这棵构造好的哈夫曼树:(经过左边路径为0,经过右边路径为1)

则可直接写出编码,例如:

A:11   B:001    C:011  D   E:0000    F:0001    G:0100    H:0101    I:1000   J:1001


为了简便起见,我们从树的左边开始考虑,即B,E,F节点。

对于节点B,其深度为3,权值为5,那么其带权路径长度为5*3 = 15;

那么我们再看一下节点B的父亲节点,其权值为9,是由权值为4和权值为5的节点B构造而成,那么即是9 = 4 + 5;

同样的再往上一层,节点B的爷爷节点,其权值为16,是由权值为9和权值为7的节点构造而成,而权值为9的节点的构造前面已经说明,则有16 = 4 + 5 + 7;

再往上一层就到根节点了。

那么到这里我们可以看到,节点B的父亲节点和爷爷节点的组成部分都有节点B的“功劳”,即节点B的权值是其另外两个的“组成部分”,那么节点B的带权路径长度即为其到根节点路径上(不包含根节点),与其(或者说是与其父节点,爷爷节点等)有父子关系的节点抽取出节点B的组成部分(包括节点B本身),再全部相加,这样的话就得到了节点B的带权路径长度为5 + 5 + 5 = 15;

同样的,节点E,F按照同样的方法进行推导。

所以我们从上面的分析得出:

每个带权叶节点到根节点的带权路径长度等于其到根节点路径上所有节点的包含该带权叶节点权值组成部分之和。

因此,最后我们推导出,所有叶节点,即整棵哈夫曼树的带权路径长度 WPL即为:

除了根节点以外,所有节点的权值之和。

如上图哈夫曼树的带权路径长度 WPL即为:

WPL = 16 + 10 + 9 + 7 + 5 + 5 + 4 + 5 + 3 + 4 + 2 + 3 + 2 + 2 + 2 + 1 + 1 + 1 = 82

有了这样的判断之后,我们便很容易计算出一颗哈夫曼树的带权路径WPL了。

因此我们可以借助一个叫做优先队列的数据结构,而优先队列的实现往往是借助于二叉堆的结构实现,在这里我们要实现的是小根堆的数据结构。一开始的时候,我们可以将所有的节点一个一个的压入队列中,每次有节点入队,队列都会进行自调整,使其保持一个小根堆的状态。当所有的节点全部入队之后,这时候我们根据以上推导出来的结论,每次取两个权值最小的节点,将其值计算之后,然后再将两个节点权值之和的节点压入队列中,直到队列中只剩下一个节点(即根节点),跳出循环体,输出最后的答案。即整棵哈夫曼树的带权路径WPL。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

哈夫曼树以及哈夫曼编码的构造步骤 的相关文章

随机推荐

  • 在 Dockerfile 中 CMD 和ENTRYPOINT可以混着用吗?

    在 Dockerfile 中 CMD 和ENTRYPOINT可以混着用吗 在 Dockerfile 中 CMD 和 ENTRYPOINT 是两个不同的指令 它们可以单独使用 也可以结合使用 CMD 指令用于指定容器启动时默认执行的命令 它可
  • 利用回调函数消灭大量分支语句if,case

    1 背景 有这样一个场景 常见的通讯程序中 根据不同的消息类型 调用不同的处理函数 类似于处理登陆 退出登陆 发送消息等类型 上古操作可能会是这样的代码 void dealLogin std cout lt lt received logi
  • Android实现获取应用程序相关信息列表的方法

    本文所述为Androdi获取手机应用列表的方法 比如获取到Android应用的软件属性 大小和应用程序路径 应用名称等 获取所有已安装的Android应用列表 包括那些卸载了的 但没有清除数据的应用程序 同时在获取到应用信息的时候 判断是不
  • 替换字符串中的括号内容(java)

    问题描述 给你一个字符串 s 它包含一些括号对 每个括号中包含一个 非空 的键 比方说 字符串 name is age yearsold 中 有 两个 括号对 分别包含键 name 和 age 你知道许多键对应的值 这些关系由二维字符串数组
  • micropython 固件开发_Micropython编译固件的操作步骤

    目标 编译STM32F4固件并刷入到我们的开发板 STM32F407VET6 1 在Linux系统下进行编译操作 windows用户可以在虚拟机下运行Linux系统 推荐下载kali Linux系统 https www kali org d
  • 16个推荐系统开放公共数据集整理分享

    本文由深度学习与NLP编译 本文主要整理了一些与推荐系统相关的高质量的数据集 整理自Stack Overflow 一些文章 推荐站点和学术实验 其中 大多数数据集都是免费 开放的 但有些不是 需要获得许可或引用作者的工作才能使用 此外 其中
  • 微信云开发——日记小程序

    真正的大师 永远都怀着一颗学徒的心 一 项目简介 前一段时间在网上看到了一个云笔记的小程序 感觉挺不错的 闲暇之余 把他改造了一波 改成了一个专门写日记的小程序 同时 还增加了类似广场的小功能 就是可以把日记设置成公开 让所有的人都能看到
  • redis持久化配置

    redis有两种持久化方式 RDB和AOF 1 RDB配置方式 默认情况下 是快照RDB的持久化方式 将内存中的数据以快照的方式写入二进制文件中 默认的文件名是dump rdb redis conf默认配置 save 900 1 save
  • java多个jdk切换不同版本无法切换且上移环境JAVA_HOME无效的解决方案

    背景 我电脑上之前安好了java19 因为一些原因要下java1 8 发现可以设置计算机里的多个jdk版本 于是兴冲冲的开始了 网上的教程很详细 我也不啰嗦 前面进行的一切顺利 但是我始终无法切换对应的版本号 一直是原来的java19 后面
  • volatile概念详解及使用场景

    文章目录 一 volatile关键字特性 1 概念 2 特性 可见性 有序性 禁止指令重排序 原子性 二 使用场景 模式1 状态标志 模式2 独立观察 independent observation 模式3 一次性安全发布 模式4 vola
  • 1.1.2 python基本数据类型与运算符

    本章引言 任何计算机语言的学习都离不开其基础中的基础 即数据类型和运算 所以要学好一门语言必须具有扎实的基础 后期是否能够灵活使用就取决于第二章 第三章内容是否深而透 变量含义 用来存储一些之后可能会变化的值 对科比投篮ID为 1 的一次投
  • 输入入栈序列判断出栈序列是否合法(c语言实现)

    题目 分别给定入栈序列和出栈序列 然后判断出栈序列是否合法 如入栈序列是 6 5 4 3 2 1 出栈序列 4 5 3 1 2 6 是合法的 3 4 6 5 2 1 是不合法的 思路 判断出栈序列是否合法的标准是 栈顶如果是需要出栈的元素
  • Unity Code  鼓励师 插件

    使用 Visual Studio Code 编写代码 有隐藏福利插件设置哦 1 打开 Code 在扩展 搜索 鼓励 多种 插件 供你选 2 看看介绍 可以自定义哦 自己安装体验吧 3 还可以使用 蔡徐坤鼓励师 4 好想 体验 有真人 鼓励师
  • c++--解决cin输入流中遇到空格结束问题

    解决cin输入流中遇到空格结束问题 cout lt lt 请输一个字符串 lt
  • 基于stm32f1的内部读写flash

    flash是存储芯片的一种 通过特定的程序可以修改里面的数据 FLASH在电子以及半导体领域内往往表示Flash Memory的意思 即平时所说的 闪存 全名叫Flash EEPROM Memory 它结合了ROM和RAM的长处 不仅具备电
  • mysql5 autoreconnect_Mysql5的auto Reconnect错误

    一 解决方案一 最近在一个J2EE项目的开发过程中 遇到了这样的问题 在服务器上部署好这个Web系统后 这时访问系统是很正常的 当把服务器的时间 例如 2008 03 31 加一天或更多天 例如 2008 04 01 2008 04 02
  • 语义分割代码阅读---评价指标mIoU的计算

    1 语义分割IoU的定义 传统意义上的IoU Intersection over Union 交并比 直观表示 公式 语义分割中的IoU 在语义分割的问题中 这两个集合为真实值 ground truth 和预测值 predicted seg
  • react、vue项目代码阅读熟悉技巧

    在没有人给你解读项目的情况下 接手到老项目该如何开始起步熟悉呢 除了要大致到了解项目业务背景 技术栈 还应该要有通用化熟悉项目的技巧 每个人熟悉项目习惯技巧都不一样 尊重每个人的习惯和想法 建议收藏以下我的分享的熟悉项目技巧 拉项目 先熟悉
  • unity异常:InvalidOperationException: Burst failed to compile the function pointer `Int32

    异常信息具体如下 InvalidOperationException Burst failed to compile the function pointer Int32 ValidateCollinear BurstManaged Uni
  • 哈夫曼树以及哈夫曼编码的构造步骤

    注意 哈夫曼树并不唯一 但带权路径长度一定是相同的 第一部分 由给定结点构造哈夫曼树 1 8个结点的权值大小如下 2 从19 21 2 3 6 7 10 32中选择两个权小结点 选中2 3 同时算出这两个结点的和5 3 从19 21 6 7