【数据结构】哈夫曼编码与前缀编码

2023-11-20

1.前缀编码

首先对于一个串可以用等长的二进制位表示,这样就叫做固定长度编码。如果可以用不等长的二进制位表示,则称之为可变长度编码。那么对于那些频度高的字符我们采用短二进制位编码,出现频度低的采用长二进制位编码的话,将会极大地减少编码长度,起到压缩数据的作用。
在一个编码方案中,没有一个编码是另外一个编码的前缀,则称这个编码方案为前缀编码。对前缀编码的解码很简单,因为没有一个码是其他编码的前缀,所以识别出第一个编码翻译为原码,再对后续的编码文件重复进行同样的操作。比如0,101,100就是一组前缀编码。00100101,就可以唯一的被识别为0,0,100,101。而不会产生二义。
引入前缀编码的话就是想用一组能唯一标识的编码来表示原数据,并且数据所占空间最小。

编码 等长编码 I 不等长编码 II 不等长编码 III
a 000 0 0
b 001 1 101
c 010 10 100
d 011 11 111
e 100 101 1101

1.对于等长编码5个字符来说,就需要至少3位,因为22=4,23=8才够用,就会浪费很多空间。
2.对于不等长编码I,abcde编码后就是011011101,那么在解码的时候就会出现0,11,0,11,101或者0,11,0,1,11,0,1等等其他错误的序列。
3.然后就出现了不等长编码III,abcde编码后序列就是01011001111101,解码的时候0,101,100,111,1101还原abcde不会出现二义。
所以编码II就不是前缀编码,编码III是前缀编码。

总之就是[1]采用不等长的编码方式就是为了压缩。[2]利用前缀编码就是解决能否唯一标识的问题。

2.哈夫曼编码与哈夫曼树

哈夫曼编码就是由哈夫曼树顺理成章得到的,上面说到了想要利用短二进制位去表示出现频度较高的字符从而达到压缩的效果。
2.1 首先Huffman树就是带权路径最小的二叉树称之为哈夫曼树,也叫最优二叉树。它的叶结点都是带有权值的,带权路径就是从叶结点出发到达根节点的路径数权值,就是该叶结点的带权路径,哈夫曼树保证所有叶结点的带权路径和最小。
WPL=∑wi*li.
以下图为例,a结点的带权路径值就是45
1=45,b结点带权路径值就是13*3=39。
huffman
2.2 然后说哈夫曼树如何构造:
首先已知各个节点的权值,现在所期望的就是带权路径和最小。所以对于权值较大的结点我们肯定希望它的路径短。
对于所有节点,我们先把每一个节点都设为一个根节点,这样就形成了n颗只有根节点的树了。
然后把权值最小的两棵树结合到一起,生成一个新的根节点,把两棵树的权值和作为新的树的根节点的权值。
对于新的森林重复上一操作,直到整个森林只剩下一棵树的时候。

以上图为例:
1.首先已知abcdef的权值,a(45)、b(13)、c(12)、d(16)、e(9)、f(5)。然后找到权值最小的两棵树f和e构成一颗新树,权值为f+e=14。
2.对于新的森林找到权值最小的两棵树c和b构成一颗新的树,权值为c+b=25。
3.重复操作,直到得到上面的那棵树。

2.3对于构造好的哈夫曼树,令左子树编码为0,右子树编码为1(也可以相反)。从根结点出发到达叶结点就可以得到哈夫曼编码:
a:0
b:101
c:100
d:111
e:1101
f:1100
这样的话存储的位数就是WPL=1*45+3*13+3*12+3*16+4*9+4*5=224位。
而用等长编码的话,abcdef一共6个字符,至少需要3位(23=8),得到的二进制编码位数为3*(45+13+12+16+9+5)=300位。
这里共压缩了25%的数据,这就是哈夫曼编码的作用。哈夫曼树可以设计出总成都最短的二进制前缀编码。

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

【数据结构】哈夫曼编码与前缀编码 的相关文章

随机推荐

  • arthas 线上更新代码不生效的问题Memory compiler error, exception message: Compilation Error

    arthas 线上更新代码的场景 线上代码bug 参数值不对 if判断 代码写错了 应用场景不对 导致代码报错出现问题 这个时候我们可以避免版本的发布就不走hostfix分支发布 应为自动化部署比较麻烦 需要jenkins打包推镜像 我们小
  • ubuntu 20.04 docker安装emqx 最新版本或指定版本

    要在Ubuntu 20 04上使用Docker安装EMQX EMQ X Broker 的4 4 3版本 您可以执行以下步骤 1 更新系统包列表 sudo apt update 2 安装Docker sudo apt install dock
  • MAttNet

    PyTorch Implementation of MAttNet Introduction This repository is Pytorch implementation of MAttNet Modular Attention Ne
  • 继承,重载函数,派生函数

    继承是类与类之间的关系 是一个很简单很直观的概念 与现实世界中的继承 例如儿子继承父亲财产 类似 继承 Inheritance 可以理解为一个类从另一个类获取成员变量和成员函数的过程 例如类B继承于类A 那么B就拥有A的成员变量和成员函数
  • 【软硬件通信】ESP32 Arduino 服务端 控制舵机

    1 安装esp32开发环境 搭建ESP32开发环境 2 编写舵机驱动程序 include
  • javaScript基础面试题---找出多维数组最大值

    function fnArr arr var newArr arr forEach item index gt newArr push Math max item return newArr console log fnArr 4 5 1
  • python 猫狗二分类简单实现

    1 数据集介绍 需要数据集可以在下面留言 数据集一共有猫图片 6000张 有狗图片 6000张 图片已经被命名为 0 1 jpg 0 6000 jpg 猫 1 0 jpg 1 6000 jpg 狗 照片读取代码如下 import numpy
  • C/C++在线编译器

    一直以来都喜欢用手机看书 尤其是在上班时 看的最多的是编程一类的书 主要是C 看着就想写写代码 可是电脑用不能用 怎么办 于是想到用UC浏览器找找看网上有没有在线的编译器 想什么时候写代码都可以验证 于是就找了几个 各有千秋吧 中文的我没找
  • python中用于返回元组中元素最小值的是_10个示例带你掌握python中的元组

    数据结构是任何编程语言的关键部分 为了创建强大而性能良好的产品 必须非常了解数据结构 在本文中 我们将研究Python编程语言的重要数据结构 元组 元组是用逗号分隔并括在括号中值的集合 与列表不同 元组的元素是不可变的 不变性可以视为元组的
  • 阿里巴巴开发手册-并发处理

    强制 获取单例对象要线程安全 在单例对象里面做操作也要保证线程安全 说明 资源驱动类 工具类 单例工厂类都需要注意 强制 线程资源必须通过线程池提供 不允许在应用中自行显式创建线程 说明 使用线程池的好处是减少在创建和销毁线程上所花的时间以
  • 图像数据压缩方法

    数据压缩方法 数据能够进行压缩 是因为数据中存在或多或少的冗余信息 而对于视频和音频等多媒体信息 更可以利用人类自身的感知冗余 失真 特点来实现更高的压缩比例 衡量压缩算法的三个主要性能指标如下 压缩比 压缩质量 失真 压缩与解压缩效率 注
  • 企业如何实现上云、选云和买云的三步走

    云计算的发展进入稳定期后 客户的关注点已经聚焦到了混合云 从混合云的视角出发来看 公有云厂家的产品已经琳琅满目非常成熟了 从传统的虚拟服务器 存储 网络 到数据库 中间件到 Docker 等 各大主流公有云厂商都推出了具有相当竞争力的产品
  • 交叉连接查询课程号

  • C++的引用

    C 的引用 一 什么是引用 1 1声明方法 1 2为什么C 要加入引用类型的变量 引用类型与指针类型的比较 二 引用类型在函数中的实际使用 2 1传参数时特殊情况 临时变量 三 引用的更多使用 3 1 常引用 C 引用就是一个变量的别名 一
  • Java实现文件传输

    Java实现文件传输 在Java编程中 我们可以使用各种方法实现文件传输 文件传输是将文件从一个位置传输到另一个位置的过程 可以用于各种应用场景 如文件备份 文件共享等 下面我将介绍一种基于Socket的Java文件传输实现方法 首先 我们
  • C++程序中使用openpose预测关节点坐标的简易实现

    C 程序中使用openpose预测关节点坐标的简易实现 虽然在openpose的官网上已经给出了很多可用的demo 但是如果我们在自己的C 项目中想要使用openpose来预测三维关键点官网给出的例子不是很适用 所以我现在给出了C 程序中使
  • Go切片排序

    Go 语言标准库提供了sort包 用于对切片和用户定义的集合进行排序 具体示例如下 基本排序 package main import fmt sort func main float 从小到大排序 f float64 5 2 1 3 0 7
  • 解决elementUI的对话框(Dialog)组件点击自动跳转到页面顶部问题

  • Python身份运算符(is , is not) 和比较运算符(==,!=)区别

    学习的时候无意中翻到 就在这里稍微记录一下 从名字上看 身份运算符的意思是 运算 两个对象的身份的 那怎么 运算 两个对象的身份呢 那么就自然而然想到比较两个对象的身份是否是相同的 在这里的身份就是他们的id 也就是内存地址 所以身份运算符
  • 【数据结构】哈夫曼编码与前缀编码

    1 前缀编码 首先对于一个串可以用等长的二进制位表示 这样就叫做固定长度编码 如果可以用不等长的二进制位表示 则称之为可变长度编码 那么对于那些频度高的字符我们采用短二进制位编码 出现频度低的采用长二进制位编码的话 将会极大地减少编码长度