当前位置: 首页 > news >正文

哈夫曼树和哈夫曼编码

哈夫曼编码一般用来对字符串进行编码格式的表示。其中要克服的最大问题,莫过于就是一串由0或者1组成的编码,你无法区分哪些01组成的编码部分是属于哪些字符的,因此哈夫曼编码的出现解决了这个问题。

在介绍哈夫曼编码之前,先介绍以下哈夫曼树:

哈夫曼树(Huffman Tree),又称最优二叉树,是一种带权路径长度最短的二叉树,由美国数学家大卫·哈夫曼(David A. Huffman)在1952年提出。以下从基本概念、构建过程和应用场景等方面进行介绍:

  • 基本概念

    • 路径和路径长度:在一棵树中,从一个结点到另一个结点所经过的分支序列称为路径,路径上的分支数目称为路径长度。

    • 结点的权和带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为从根结点到该结点的路径长度与该结点权值的乘积。

    • 树的带权路径长度:树中所有叶子结点的带权路径长度之和,记为WPL。哈夫曼树就是WPL最小的二叉树。

  • 构建过程

    • 假设有n个权值,将这些权值看成是有n棵树的森林(每棵树仅有一个结点)。

    • 从森林中选出根结点权值最小的两棵树作为左右子树构造一棵新的二叉树,新二叉树的根结点权值为其左右子树根结点权值之和。

    • 从森林中删除这两棵树,同时将新得到的二叉树加入森林中。

    • 重复上述步骤,直到森林中只剩下一棵树为止,这棵树就是哈夫曼树。

  • 特点

    • 哈夫曼树是一棵二叉树,且所有的非叶子结点都有两个子树,不存在度为1的结点。

    • 权值越大的叶子结点越靠近根结点,而权值越小的叶子结点越远离根结点。

  • 应用场景

    • 数据压缩:哈夫曼编码是一种常用的无损数据压缩算法。通过对数据中不同字符出现的频率进行统计,构造哈夫曼树,为每个字符分配一个唯一的二进制编码,频率高的字符编码短,频率低的字符编码长,从而实现数据的压缩。

    • 信息检索:在一些需要快速检索的数据结构中,可以利用哈夫曼树的思想来优化查找过程,提高查找效率。

    • 霍夫曼编码:在通信领域,用于构造一种编码方式,使得通信中传输的数据量最小,提高信道的利用率。

通过应用场景我们可以发现哈夫曼树就是主要实现单个字符唯一编码的功能。

我们来用举例的方法来讲解哈夫曼树:

一句话:

        i like bananas

    • 在句子“i like bananas”中,统计每个字母的出现次数如下:

      • a:3

      • b:1

      • i:2

      • k:1

      • l:1

      • n:2

      • s:1

      • 空格:2

      • e:1

然后开始搭建哈夫曼树:

  1. 初始节点(叶子节点):

    • 节点 a,权重(出现次数)为 3

    • 节点 b,权重为 1

    • 节点 i,权重为 2

    • 节点 k,权重为 1

    • 节点 l,权重为 1

    • 节点 n,权重为 2

    • 节点 s,权重为 1

    • 节点 e,权重为 1

  2. 第一次合并:

    • 取出权重最小的 b(权重 1)和 k(权重 1),创建新节点 N1,权重为 1 + 1 = 2 。

    • N1 的左子节点为 b,右子节点为 k

    • 此时节点情况:

      • 节点 a,权重 3

      • 节点 i,权重 2

      • 节点 l,权重 1

      • 节点 n,权重 2

      • 节点 s,权重 1

      • 节点 e,权重 1

      • 节点 N1,权重 2

  3. 第二次合并:

    • 取出权重最小的 l(权重 1)和 s(权重 1),创建新节点 N2,权重为 1 + 1 = 2 。

    • N2 的左子节点为 l,右子节点为 s

    • 此时节点情况:

      • 节点 a,权重 3

      • 节点 i,权重 2

      • 节点 n,权重 2

      • 节点 e,权重 1

      • 节点 N1,权重 2

      • 节点 N2,权重 2

  4. 第三次合并:

    • 取出权重最小的 e(权重 1)和 N1(权重 2),创建新节点 N3,权重为 1 + 2 = 3 。

    • N3 的左子节点为 e,右子节点为 N1

    • 此时节点情况:

      • 节点 a,权重 3

      • 节点 i,权重 2

      • 节点 n,权重 2

      • 节点 N2,权重 2

      • 节点 N3,权重 3

  5. 第四次合并:

    • 取出权重最小的 i(权重 2)和 N2(权重 2),创建新节点 N4,权重为 2 + 2 = 4 。

    • N4 的左子节点为 i,右子节点为 N2

    • 此时节点情况:

      • 节点 a,权重 3

      • 节点 n,权重 2

      • 节点 N3,权重 3

      • 节点 N4,权重 4

  6. 第五次合并:

    • 取出权重最小的 a(权重 3)和 N3(权重 3),创建新节点 N5,权重为 3 + 3 = 6 。

    • N5 的左子节点为 a,右子节点为 N3

    • 此时节点情况:

      • 节点 n,权重 2

      • 节点 N4,权重 4

      • 节点 N5,权重 6

  7. 第六次合并:

    • 取出权重最小的 n(权重 2)和 N4(权重 4),创建新节点 N6,权重为 2 + 4 = 6 。

    • N6 的左子节点为 n,右子节点为 N4

    • 此时节点情况:

      • 节点 N5,权重 6

      • 节点 N6,权重 6

  8. 第七次合并:

    • 取出 N5(权重 6)和 N6(权重 6),创建新节点 Root(根节点),权重为 6 + 6 = 12 。

    • Root 的左子节点为 N5,右子节点为 N6

通过上述步骤我们得到了哈夫曼树:

然后我们将向左移动的路径设置为0,向右的为1

我们的哈夫曼树就变为:

有了哈夫曼树,我们的哈夫曼编码也就得到了,每个字符的编码就为从根路径到指定字符的叶子节点:

  • a:出现次数为 3,编码是 00

  • n:出现次数为 2,编码是 100

  • i:出现次数为 2,编码是 110

  • 空:出现次数为 2,编码是 111

  • l:出现次数为 1,编码是 0110

  • k:出现次数为 1,编码是 1011

  • e:出现次数为 1,编码是 0111

  • b:出现次数为 1,编码是 010

  • s:出现次数为 1,编码是 1010

相关文章:

  • 【自存】python使用matplotlib正常显示中文、负号
  • 智能工厂边缘计算:从数据采集到实时决策
  • 【Linux】SELinux 的基本操作与防火墙的管理
  • 力扣-链表-2 两数相加
  • 课程10. 聚类问题
  • js逆向绕过指纹识别
  • 5个情感丰富GPT-4o图像提示词(不是吉卜力风格)
  • PyTorch数据集与数据集加载
  • 情绪ABC——AI与思维模型【93】
  • Semaphore的详细源码剖析
  • 组合模式深度解析:构建灵活树形结构的终极指南
  • 变更需求代价:影响分析
  • OpenCv实战笔记(2)基于opencv和qt对图像进行灰度化 → 降噪 → 边缘检测预处理及显示
  • AUTOSAR_BSW_从入门到精通学习笔记系列_EcuM
  • 仓颉编程语言:面向未来的全场景智能开发新范式
  • LeetCode 102题解 | 二叉树的层序遍历
  • BUUCTF——Fake XML cookbook
  • 13:图像处理—畸变矫正详解
  • 57认知干货:AI机器人产业
  • AIDC智算中心建设:计算力核心技术解析
  • 贵州黔西市游船倾覆事故致9人死亡1人失联
  • 魔都眼|上海环球马术冠军赛收官,英国骑手夺冠
  • 苏丹外交部:苏丹西部一城市约300名平民遭杀害
  • 5月2日,全社会跨区域人员流动量完成29275.4万人次
  • 澳大利亚大选今日投票:聚焦生活成本与“特朗普问题”
  • 居委业委居民群策群力,7位一级演员来到上海一小区唱戏