哈夫曼树你需要了解一下

    • 哈夫曼树介绍
    • 哈夫曼数特点
    • 哈夫曼应用场景
    • 哈夫曼构建过程
    • 哈夫曼树示例
    • 拓展

哈夫曼树介绍

哈夫曼树(Huffman Tree)是一种特殊的二叉树,也被称为最优二叉树。在计算机科学中,它是由权值作为叶子节点构造出来的一种二叉树。哈夫曼树的特点是,对于给定的n个权值,构造出的哈夫曼树具有最小的带权路径长度(WPL)。

具体来说,哈夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码。这个变长编码表是通过评估来源符号出现机率的方法得到的。出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码。这样,编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

在构建哈夫曼树时,通常规定生成的哈夫曼树中每个结点的左子树根结点的权小于等于右子树根结点的权。对于给定的n个权值,构造出的哈夫曼树有n个叶子结点。

哈夫曼树是由哈夫曼在1951年提出的。当时,他在麻省理工学院(MIT)攻读博士学位,并和修读信息论课程的同学面临选择完成学期报告或期末考试。他的导师罗伯特·法诺出的学期报告题目是:查找最有效的二进制编码。

哈夫曼在研究这个问题的过程中,发现无法证明哪个已有编码是最有效的,因此他转向新的探索,最终发现了基于有序频率二叉树编码的想法,并很快证明了这个方法是最有效的。哈夫曼使用自底向上的方法构建二叉树,避免了次优算法香农-范诺编码(Shannon–Fano coding)的最大弊端──自顶向下构建树。

因为构造这种树的算法是最早由哈夫曼于1952年提出的,所以被称之为哈夫曼树。哈夫曼树是带权路径长度WPL最小的二叉树,它是一种最优二叉树。

在这里插入图片描述

哈夫曼数特点

哈夫曼树的主要特点包括:

  1. 带权路径和最小:哈夫曼树是带权路径和中权值最小的树,也被称为最优二叉树。这意味着在所有可能的二叉树中,哈夫曼树能够使得树的带权路径长度最小。
  2. 不存在度为1的节点:哈夫曼树中不存在度为1的节点,即所有节点都有至少两个子节点。
  3. 总结点数:对于n个叶子节点的哈夫曼树,总共有2n-1个节点。
  4. 权值越小的节点到根节点的路径越长:在哈夫曼树中,权值越小的节点离根节点越远,路径也就越长。
  5. 最优二叉树个数不唯一:由于构建过程中并未严格区分左右子树,所以最优二叉树个数并不唯一。
    除了上述提到的特点外,哈夫曼树还有其他一些特点:
  6. 二叉树:哈夫曼树是一种二叉树,具有二叉树的特性,例如每个节点最多只有两个子节点,且子节点分为左子树和右子树。
  7. 有序树:哈夫曼树是一种有序树,左子树和右子树是有顺序的,次序不能任意颠倒。这也意味着即使某个节点只有一个子节点,也需要区分它是左子树还是右子树。
  8. 构建过程:哈夫曼树的构建过程通常采用优先队列的方式,将权值最小的两个节点合并为一个新的节点,然后将新节点的权值加入到优先队列中。这个过程会不断重复,直到优先队列中只剩下一个节点为止。
  9. 动态构建:哈夫曼树也可以动态构建,即每次只处理一部分数据,然后根据处理结果动态地构建哈夫曼树。这种构建方式可以更加灵活地处理数据,并且可以实时地更新哈夫曼树。
  10. 应用广泛:哈夫曼树被广泛应用于各种领域,例如数据压缩、编码解码、序列比对、机器学习、图像处理和声音处理等。

在这里插入图片描述

哈夫曼应用场景

哈夫曼树是一种广泛使用的数据结构,主要用于构建最优编码,在许多领域都有应用。

1. 数据压缩 :哈夫曼编码是一种无损数据压缩方法,通过使用较短的编码来表示常见的符号,从而减少数据的大小。它被广泛应用于图像、音频和视频等数据的压缩。
2. 编码解码 :哈夫曼树可以用于构建最优编码,将信息转换为二进制形式,并可以在接收端使用相同的哈夫曼树解码恢复原始信息。这种编码解码技术被广泛应用于通信和网络传输领域。
3. 序列比对 :在生物信息学中,哈夫曼树被用于DNA序列的比对和相似度计算。通过构建基因序列的哈夫曼树,可以比较不同基因序列之间的相似性和差异。
4. 机器学习 :哈夫曼树也被用于机器学习算法中,例如决策树和聚类算法。通过构建特征的哈夫曼树,可以优化特征选择和分类器的构建。
5. 图像处理 :哈夫曼树可以用于图像的压缩和编码,以及图像特征提取和分类。
6. 声音处理 :哈夫曼树可以用于声音的压缩和编码,以及语音识别和合成。
7. 优化技术 :哈夫曼树是一种优化技术,可以用于解决各种优化问题,例如最短路径问题、最小生成树问题等。

哈夫曼树在许多领域都有广泛的应用,是一种非常实用的数据结构和算法。

在这里插入图片描述

哈夫曼构建过程

哈夫曼树的构建过程如下:

  1. 准备阶段:给定N个权值作为N个叶子结点,构造一棵二叉树,该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。
  2. 创建阶段:给定n个权值,构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
  • a. 将w1、w2、…,wn看成是有n棵树的森林(每棵树仅有一个结点);

  • b. 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;

  • c. 从森林中删除选取的两棵树,并将新树加入森林;

  • d. 重复b、c步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。

在这里插入图片描述

哈夫曼树示例

以下是使用Java实现哈夫曼树的示例代码:

import java.util.*;

class Node {
    int weight;
    Node left, right;

    Node(int weight) {
        this.weight = weight;
        left = right = null;
    }
}

class HuffmanTree {
    private static final int R = 2; // 哈夫曼树中每个节点的左子树和右子树的数量

    private Node root; // 根节点

    // 构建哈夫曼树
    public void build(int[] weights) {
        int[] queue = new int[weights.length]; // 存储节点的索引
        for (int i = 0; i < weights.length; i++) {
            queue[i] = i + 1; // 将节点的索引加入队列
        }
        PriorityQueue<Node> pq = new PriorityQueue<>(R); // 使用优先队列存储节点
        for (int i = 0; i < weights.length; i++) {
            Node node = new Node(weights[i]); // 创建新节点
            pq.offer(node); // 将节点加入优先队列
            if (pq.size() > R) { // 如果优先队列中的元素数量超过R,则合并两个最小节点
                Node min1 = pq.poll(); // 取出最小节点1
                Node min2 = pq.poll(); // 取出最小节点2
                Node parent = new Node(min1.weight + min2.weight); // 创建父节点
                parent.left = min1; // 设置左子树
                parent.right = min2; // 设置右子树
                pq.offer(parent); // 将父节点加入优先队列
            }
            if (i == weights.length - 1) { // 如果遍历完所有节点,则根节点为当前队列中最大的节点
                root = pq.poll();
            }
        }
    }
}

优先队列在构建哈夫曼树时的作用是维护和调整节点的优先级。优先队列中的节点按照其权值的大小进行排序,权值最小的节点位于队列的前端。每次从队列中取出权值最小的两个节点,将它们合并为一个新的节点,新的节点的权值等于这两个节点的权值之和。然后将新的节点重新插入到优先队列中。这个过程不断重复,直到优先队列中只剩下一个节点,这个节点就是构建出的哈夫曼树的根节点。
通过使用优先队列,我们可以高效地找到权值最小的两个节点,并快速地合并它们。这是因为在优先队列中,权值最小的节点始终位于队列的前端,我们可以直接取出这两个节点进行合并。这极大地简化了构建哈夫曼树的过程,并提高了效率。

在这里插入图片描述

拓展

AVL树你需要了解一下

红黑树你需要了解一下

满二叉树你需要了解一下

完全二叉树你需要了解一下

在这里插入图片描述

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

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

相关文章

【UE】用样条线实现测距功能(上)

目录 效果 步骤 一、创建样条网格体组件3D模型 二、实现点击连线功能 三、实现显示两点间距离功能 效果 步骤 一、创建样条网格体组件3D模型 创建一个圆柱模型&#xff0c;这里底面半径设置为10mm&#xff0c;高度设置为1000mm 注意该模型的坐标轴在如下位置&#xff1…

集团投融资大数据平台解决方案

一、项目背景 项目为集团型公司大数据平台项目&#xff0c;整个项目周期约为6个月&#xff0c;整体呈现了对外的数据大屏驾驶仓和对内的看板报表&#xff0c;减少了客户内部数据上报和报表制作的重复工作量&#xff0c;为集团数据决策奠定基础。 二、项目目标 战略层&#xff…

c++ std::variant用法

std::variant Union类型的问题&#xff1a; 无法知道当前使用的类型是什么union无法自动调用底层数据成员的析构函数。联合体无法对其内部的数据属性的生命周期的全面支持&#xff0c;因为当外部代码调用Union时在切换类型&#xff0c;它无法做到对当前使用的对象&#xff0c…

Java(五)(Object类,克隆,Objects类,包装类,StringBuilder,StringJoiner,BigDecimal)

目录 Object类 Object类的常见方法: 克隆 浅克隆 深克隆 Objects类 包装类 StringBuilder StringJoiner BigDecimal Object类 Object类是java中的祖宗类,因此,Java中所有的类的对象都可以直接使用object类提供的一些方法 Object类的常见方法: public String toStrin…

【黑马甄选离线数仓day01_项目介绍与环境准备】

1. 行业背景 1.1 电商发展历史 电商1.0: 初创阶段20世纪90年代&#xff0c;电商行业刚刚兴起&#xff0c;主要以B2C模式为主&#xff0c;如亚马逊、eBay等 ​ 电商2.0: 发展阶段21世纪初&#xff0c;电商行业进入了快速发展阶段&#xff0c;出现了淘宝、京东等大型电商平台&a…

Halcon Solution Guide I basics(3): Region Of Interest(有兴趣区域/找重点)

文章目录 文章专栏前言文章解读前言创建ROI案例1&#xff1a;直接截取ROI手动截取ROI 总结ROI套路获取窗口句柄截取ROI区域获取有效区域 Stop组合 文章专栏 Halcon开发 Halcon学习 练习项目gitee仓库 CSDN Major 博主Halcon文章推荐 前言 今天来看第三章内容&#xff0c;既然是…

忘记7-zip密码,如何解压文件?

7z压缩包设置了密码&#xff0c;解压的时候就需要输入正确对密码才能顺利解压出文件&#xff0c;正常当我们解压文件或者删除密码的时候&#xff0c;虽然方法多&#xff0c;但是都需要输入正确的密码才能完成。忘记密码就无法进行操作。 那么&#xff0c;忘记了7z压缩包的密码…

代码规范之-理解ESLint、Prettier、EditorConfig

前言 团队多人协同开发项目&#xff0c;困扰团队管理的一个很大的问题就是&#xff1a;无可避免地会出现每个开发者编码习惯不同、代码风格迥异&#xff0c;为了代码高可用、可维护性&#xff0c;需要从项目管理上尽量统一和规范代码。理想的方式需要在项目工程化方面&#xff…

力扣:175. 组合两个表(Python3)

题目&#xff1a; 表: Person ---------------------- | 列名 | 类型 | ---------------------- | PersonId | int | | FirstName | varchar | | LastName | varchar | ---------------------- personId 是该表的主键&#xff08;具有唯一值的列&#…

设计循环队列,解决假溢出问题

什么是假溢出&#xff1f; 当我们使用队列这种基本的数据结构时&#xff0c;很容易发现&#xff0c;随着入队和出队操作的不断进行&#xff0c;队列的数据区域不断地偏向队尾方向移动。当我们的队尾指针指向了队列之外的区域时&#xff0c;我们就不能再进行入队操作了&#xff…

【shell】循环语句(for、while、until)

目录 一、循环语句的特点 二、三种常用的循环 2.1 for循环 2.2 while循环 2.3 until循环 2.4 死循环 2.5 关于continue和break以及exit 三、实操案例 3.1 累加1到100&#xff08;5种办法&#xff0c;穿插多种运算习惯&#xff09; 3.2 批量修改文件名称 3.3 pi…

yapi==使用依赖包里的类作为入参/返回值导出后没有备注

比如模块A中有个MyDemoEntity类,在B中以依赖的形式引入了A,并在B的接口中以MyDemoEntity作为返回值,导出到YAPI发现MyDemoEntity的备注没了。 解决: 将A的内容安装到本地MAVEN仓库,并且需要将源码也一起安装 <build><resources><resource><director…

记录--手写一个 v-tooltip 指令

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 日常开发中&#xff0c;我们经常遇到过tooltip这种需求。文字溢出、产品文案、描述说明等等&#xff0c;每次都需要写一大串代码&#xff0c;那么有没有一种简单的方式呢&#xff0c;这回我们用指…

第一百七十六回 如何创建渐变色边角

文章目录 1. 概念介绍2. 实现方法3. 代码与细节3.1 示例代码3.2 代码细节 4. 内容总结 我们在上一章回中介绍了"如何创建放射形状渐变背景"相关的内容&#xff0c;本章回中将介绍"如何创建渐变色边角".闲话休提&#xff0c;让我们一起Talk Flutter吧。 1.…

Axios使用方式

ajax是JQUERY封装的XMLHttprequest用来发送http请求 Axios简单点说它就是一个js库,支持ajax请求,发送axios请求功能更加丰富,丰富在哪不知道 1.npm使用方式 vue项目中 npm install axios 2.cdn方式 <script src"https://unpkg.com/axios/dist/axios.min.js">…

行情分析——加密货币市场大盘走势(11.22)

大饼昨日晚上打了止损&#xff0c;笔者入场了空单&#xff0c;目前来看上涨乏力&#xff0c;下跌是必然的&#xff0c;昨日的下跌跌破了蓝色上涨趋势线&#xff0c;而今日白天开始反弹&#xff0c;别着急抄底&#xff0c;下跌还没有结束。 空单策略&#xff1a;入场36500 止盈…

为UE和Unity开发者准备的Godot指南

为UE和Unity开发者准备的Godot指南 ——两位大哥打架&#xff0c;请带上我 这两天游戏行业又开始热闹了&#xff0c;昨天两条信息直接刷爆朋友圈&#xff0c;最大的两家游戏引擎公司怼起来了。 《为Unity开发者准备的虚幻引擎指南》&#xff1a; 为Unity开发者准备的虚幻引擎指…

Autocad2020切换经典界面

Autocad2020切换经典界面 1.更改1.1设置另存为 1.更改 1.1设置另存为

SQL语句执行过程

一条 SQL 的执行过程可以大致分为以下几个步骤&#xff1a; 连接器&#xff1a; ○ 客户端与数据库建立连接&#xff0c;并发送 SQL 语句给数据库服务。 ○ 连接器验证客户端的身份和权限&#xff0c;确保用户有足够的权限执行该 SQL 语句。查询缓存&#xff1a; ○ 连接器首先…

Redis面试内容,Redis过期策略,Redis持久化方式,缓存穿透、缓存击穿和缓存雪崩,以及解决办法

文章目录 一、redis什么是RedisRedis使用场景1、缓存2、数据共享[分布式](https://so.csdn.net/so/search?q分布式&spm1001.2101.3001.7020)3、分布式锁4、全局ID5、计数器6、限流7、位统计 Redis有5中数据类型&#xff1a; SSHLZRedis中一个key的值每天12点过期&#xff…