哈夫曼编码详细证明步骤

news2025/1/4 17:47:40

关于哈夫曼编码,想必大家都很清楚,这里来讲解一下他的详细证明方法。代码的话就不给了网上一大堆,我再给也没什么意思,这里主要讲明白正确性的证明。我将采取两种方法进行证明,一种常规的方法,还有一种采取强数学归纳法证明。如果你已经了解了哈夫曼可以直接去看证明的正确性

(由于画图软件问题,图中有一些竖线忽略即可)

这里写目录标题

  • 一:编码
    • 1.固定长度的编码
    • 2.变长的编码
    • 3.非前缀的变长编码
    • 4.变长与定长的编码比较
  • 二:编码与二叉树的关系
    • 1.定长的编码与树
    • 2.变长的编码与树
      • 前缀编码
      • 非前缀编码
  • 三:哈夫曼算法的描述
    • 1.哈夫曼算法解决的问题
    • 2.哈夫曼算法的步骤
  • 四:哈夫曼算法的正确性证明
    • 1.第一种证明方法(常规的方法)
      • (1)最优子结构性质的证明
      • (2)贪心选择性质的证明
      • (3) 这两个性质的关系
    • 2.第二种证明方法(数学归纳证明,采用强归纳法)

一:编码

1.固定长度的编码

对于编码问题最先想到的就是固定长度的编码例如

字母编码
A00
B01
C10
D11

2.变长的编码

这时我们就要想了是不是还有一个更优的编码,既然有定长的编码,自然的就会想到变长的编码,什么是变长的编码呢

字母编码
A0
B1
C01
D10

这种就是边长的编码,但是这种编码又有一种问题
如果我们的编码是0110,它对应的字母是什么呢?
我们发现它对应多种的字母如:ABBA,ABD
那这种编码就没有意义了,因为这种编码我们是没有办法解码的,解不了码就不知道传输的信息是什么了,自然也就没有意义了。

这种情况什么导致的呢,是因为A的编码是C的编码的前缀这就导致了二义性

3.非前缀的变长编码

既然是因为前缀导致了二义性,那就自然而然的会采用非前缀编码非前缀编码大家肯定都知道是什么意思了,这里来举一个例子:

字母编码
A0
B10
C110
D111

这种还会产生歧义吗?:
随便写一个编码
1010111:BBD
10111110: BDC
发现除了一些没有的编码比如101这种没有对应的坏码(这里不是哈夫曼的内容,那是检错校验的内容) 外其他的都是可以解码的。

4.变长与定长的编码比较

对于定长的编码的平均长度肯定就是固定的了,对于变长的编码就与编码的长度和他出现的概率有关了:例如上面的定长的平均编码长度是2,变长的话就先假设概率依次对应的是0.6,0.2,0.1,0.1;他的平均长度就是
∑ x ∈ {字母的集合} p ( x ) ⋅ len ( x ) = 0.6 ∗ 1 + 0.2 ∗ 2 + 0.1 ∗ 3 + 0.1 ∗ 3 = 1.6 \sum_{x \in \text{{\{字母的集合\}}}} p(x) \cdot \text{{len}}(x) = 0.6 * 1+0.2 * 2+0.1*3+0.1 * 3=1.6 x{字母的集合}p(x)len(x)=0.61+0.22+0.13+0.13=1.6
发现变长的比定长的要小。

二:编码与二叉树的关系

1.定长的编码与树

根据上面的定长编码,画一个二叉树
在这里插入图片描述
二叉树向左为0向右为1

2.变长的编码与树

前缀编码

在这里插入图片描述

非前缀编码

在这里插入图片描述
通过这几个例子我们发现二叉树与编码是存在一一对应的关系的。

三:哈夫曼算法的描述

1.哈夫曼算法解决的问题

哈夫曼是为了解决最优的非前缀编码问题,即平均编码长度的最小值,通过前面的例子可知编码的长度与树的深度是一样的。所以我们希望
∑ x ∈ {树的叶子节点} p ( x ) ⋅ len ( x ) \sum_{x \in \text{{\{树的叶子节点\}}}} p(x) \cdot \text{{len}}(x) x{树的叶子节点}p(x)len(x) 最小(注释:树的平均深度最小那么对应的平均编码长度就最小)

2.哈夫曼算法的步骤

假设给出的字母集合每一个字母都是一个单独的树,这些树组成集合TG,且对应于x∈TG设他的概率为p(x)

step 1: 从TG中选择概率最小的树a,和概率次小的树b合并。

step 2: 把step 1得到的新的树加入TG,并且把其概率设为p(a)+p(b),然后把a,b从TG中划掉

step 3: 重复上述步骤直到只剩下一棵树

所以哈夫曼就是把一个森林维护成树的过程

这里使用上述的非前缀编码举例子

字母概率
A0.6
B0.2
C0.1
D0.1

TG集合为:
在这里插入图片描述
(中间那条线为画图软件问题,无特殊含义)

step 1: 从TG中选择概率最小的树C,和概率次小的树D合并。

step 2: 把step 1得到的新的树加入TG,并且把其概率设为p(a)+p(b),然后把a,b从TG中划掉
在这里插入图片描述

TG变成了A,B,E树的集合C,D变成了E的子节点

step 3重复上述步骤:选择最小的合并,并且划去被合并的(最小的B,次小的E)
TG变成了A F的集合:
在这里插入图片描述
然后继续
在这里插入图片描述
这时TG就只有一棵树了,算法结束

然后看一下他们的编码,(二叉树向左是0向右是1)

字母编码
A0
B10
C110
D111

以上就是哈夫曼的所有步骤

四:哈夫曼算法的正确性证明

接下来就到了重头戏,正确性的证明

证明之前为了方便证明先说明一些符号的含义:
AG: 代表字母的集合
TG: 代表字母对应的树的集合(即每一个字母都看做一棵树,和上面的含义一样)
TAG: 字母最后构成的平均深度最小的二叉树
|TAG|: 表示他的最小平均深度
**a,b:**字母集合中概率最小和次小的字母
Ta: TG中概率最小的树
Tb: TG中概率次小的树

1.第一种证明方法(常规的方法)

贪心的证明往往就是证明贪心选择性质,和最优子结构性质然后就可以得到该算法是正确的

先确定一下子问题是什么:
在这里插入图片描述
他的子问题就是把最小的和次小的字母合成一个字母之后的树,合并之后的字母的概率为p©+p(D)
在这里插入图片描述

(1)最优子结构性质的证明

最优子结构就是原问题的最优解是子问题的最优解构成的:
子问题与原问题的关系是什么呢?
设T表示原来的树
T表示合并之后的树

根据上面的子问题图解可知,T是T的子问题

因为T中的最小概率的节点a和次小的节点b比T的节点c的深度要大一,所以
|T|=|T|+p(a)+p(b)
(例如上图的C,D合并成E之后树的平均深度就少了p( C)+p(D) ( @注解:算平均深度的时候就是只有叶节点,叶节点才是我们想要编码的字母)
设|T|是最优解,如果子问题最优的不是|T|而是|T*|那么|T * |+p(a)+p(b)才是最优的,与|T|是最优解产生矛盾,所以最优子结构得证

(2)贪心选择性质的证明

既然它是贪心选择,那么只要最开始的时候合并的两个树是Ta,Tb那就说明他是以贪心选择开始的(即TAG的最深的两个节点就是节点a,b)
设一开始合并的是Tx,Ty:
那就有三种情况

第一种情况Tx,Ty就是Ta,Tb
第二种情况Tx,Ty不是Ta,Tb
第三种情况Tx,Ty中只有一个Ta或Tb
对于第一种情况,那么他就是以贪心选择开始的;
对于第二三种情况证明是类似的,这里证明更难的第二种:
那就把它换成Ta,Tb构成新的一棵树TAG*:换之后的影响是什么呢?考虑一下:
因为除了Tx,Ty,Ta,Tb其他的节点都是不变的所以只需要考虑这四个即可
|TAG| - |TAG *|=
p(x)(x在TAG的深度 - x在TAG*的深度)+
p(y)(y在TAG的深度 - y在TAG*的深度) +
p(a)(a在TAG的深度 - a在TAG*的深度) +
p(b)(b在TAG的深度 - b在TAG*的深度)
( 因为x,y与a,b交换所以他们的深度也就交换了即深度x=深度a 深度y=深度b或则 深度y=深度a 深度x=深度b其实这两个是一种情况深度x=深度a 深度y=深度b也可以表示 深度y=深度a 深度x=深度b因为我们取的下x,y都是随机的,x与y可以是任何值,所以说他俩交换之后,x仍然是x,y仍然是y)

这里计算时设a,x交换b,y交换
这样上面的式子可以化为

|TAG| - |TAG *|=
p(x)(a在TAG*的深度 - x在TAG*的深度)+
p(y)(b在TAG*的深度 - y在TAG*的深度) +
p(a)(x在TAG*的深度 - a在TAG*的深度) +
p(b)(y在TAG*的深度 - b在TAG*的深度)

={p(x)-p(a)}*(a在TAG *的深度 - x在TAG 的深度)+{p(y)-p(b)}(b在TAG *的深度 - y在TAG *的深度)
>=0
*(注解:为什么会大于等于零,因为p(a),p(b)是最小的,并且在TAG 中a,b节点是最深得)
又因为TAG是最优解,所以有|TAG| - |TAG *|<=0
所以可以得到|TAG| = |TAG *|,得证TAG *也是一个最优解
所以他总是以贪心选择开始,并且选择完之后又出现一个类似的子问题,还是重复上述的步骤。

(3) 这两个性质的关系

这里特别说明一下贪心选择性质:我看网上的定义都是这样的经过一系列的局部最优选择最后可以构成整体最优解。我感觉这时不准确的,这不就是贪心的定义吗,这样和贪心有啥区别呢?我的理解是当前的局部最优选择可以构成该问题的最优解(注:我说的是该问题不是整体问题,如果他再满足最优子结构那就是满足贪心算法了,后面给出公式后进行详解)

满足这两个性质之后就可以说他是满足贪心的
如果只满足贪心选择,就只能说明这一步选择是最优解的一部分,但是对于选择完之后剩下的子问题,我们不能确定是不是他的最优解构成原问题的最优解。
如果只满足最优子结构那么他就不能说明他是贪心选择得来的。

其实就是一个等式关系:
原问题最优解=这一步的局部最优解+选择完之后子问题的最优解。
然后子问题的最优解又可以看作原问题最优解,再次使用上述公式求得。

(有了这个等式之后我们再去理解一下,我说的贪心选择性质:当前的局部最优选择可以构成该问题的最优解。回想一下我们证明贪心选择性质时的方法,我们就是证明了当前问题的最优解是由贪心选择开始的,然后又说明子问题是类似的,都是由贪心选择开始的。然后他又满足最优子结构性质,这样就可以把公式原问题最优解=这一步的局部最优解+选择完之后子问题的最优解。化为原问题最优解=这一步的局部最优解+选择完之后子问题的局部最优解+子问题选择完局部最优解之后剩下的子问题的最优解(即该子问题的子问题的最优解)。 它可以一直化简下去直到没有子问题,这样我们发现我们每一次都是选择的局部最优解最后构成整体的最优解。可见我们获得了正确答案,这样我对于贪心选择性质的定义的猜想也就加以证明了)

2.第二种证明方法(数学归纳证明,采用强归纳法)

————未完待续————

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5.以docker容器生成镜像推送到私有镜像仓库

1.创建私有仓库 1.1 拉取私有仓库镜像registry docker pull registry1.2 运行私有仓库镜像registry docker run -d -p 5001:5000 -v /data/myregistry/:/tmp/registry --privilegedtrue registry1.3 校验私有仓库registry是否安装成功 curl -XGET http://localhost:5001/v2…

Ubuntu环境下以编译源码的方式安装Vim

目录 1. Ubuntu环境 2. 下载编译vim 2.1 效果截图 3. 配置环境变量 1. Ubuntu环境 Linux chris-166 6.2.0-36-generic #37~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Oct 9 15:34:04 UTC 2 x86_64 x86_64 x86_64 GNU/Linux 2. 下载编译vim // 源码下载 chris_166chris-16…

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (一) 安装和配置

文章目录 &#x1f4d5;前言❓什么是 OpenXR❓什么是 XR Interaction Toolkit &#x1f4d5;教程说明&#x1f4d5;第一步&#xff1a;导入 OpenXR&#x1f4d5;第二步&#xff1a;导入 XR Interaction Toolkit⭐导入 Starter Assets⭐添加 Preset⭐设置 Preset Manager 的 Fil…

云ES高级监控告警

一、高级监控告警配置 1.1 操作入口 1.2 配置告警模块 1.2.1 新建联系人 添加联系人后,需要进行激活 1.2.2 新建联系人组 1.2.3 创建报警组 1.2.4 新建报警规则

城市网吧视频智能监控方案,实现视频远程集中监控

网吧环境较为复杂&#xff0c;电脑设备众多且人员流动性大&#xff0c;极易发生人员或消防事故&#xff0c;亟需改变&#xff0c;TSINGSEE青犀AI智能网吧视频监管方案可以帮助实现对网吧环境和用户活动的实时监控和管理。 1、视频监控系统 在网吧内部布置高清摄像头&#xff0…

操作系统OS/进程与线程/线程

进程和线程 进程 进程实体&#xff08;进程映像&#xff09;由PCB、程序段和数据段组成&#xff0c;其中PCB是进程存在的唯一标志。 线程 线程最直接的理解就是“轻量级进程”&#xff0c;它是一个基本的CPU执行单元&#xff0c;包含CPU现场(状态)&#xff0c;也是程序执行…

【Linux系统化学习】探索进程的奥秘 | 第一个系统调用

个人主页点击直达&#xff1a;小白不是程序媛 Linux系列专栏&#xff1a;系统化学习Linux 目录 进程的概念 进程的管理 描述进程——pcb 组织进程 进程在排队 Linux下的进程 Linux组织进程 查看进程 查看可执行程序的进程 第一个系统调用 "杀掉进程" 进程…

一些有趣的迹象:“前端已死”难道要成真了?

移动互联网的兴起&#xff0c;传统行业的数字化转型&#xff0c;大前端技术的普及&#xff0c;随之而来的就是Vue为代表的前端框架和工具的兴起&#xff0c;前端开发的门槛降低。但发展&#xff0c;稳定&#xff0c;衰落是亘古不变的事物发展规律。 一些有趣的迹象 最近逛社区…

Linux发展史与环境安装

Linux发展史与环境安装 一、Linux发展史推动技术进步的基本模式理解操作系统的发展理解Linux操作系统的发展 一、Linux的环境安装 一、Linux发展史 Linux和window XX其实都是一样的&#xff0c;定位&#xff1a;操作系统&#xff0c;企业内部&#xff0c;要给用户提供“互联网…

C语言指针强制的本质

今天看到这样一段项目代码&#xff0c;某个函数传入了一个void类型的指针&#xff0c;并在函数内部将其强转为了某结构体类型指针&#xff0c;利用该指针获取结构体中变量之后&#xff0c;又将指针转换为char类型并偏移结构体大小的长度获取数据。代码如下 void recv_omu_data(…

为什么esp8266刷入了固件,无法接受AT指令

我遇到的解决方法是&#xff1a;是串口调试助手出了问题。所以需要更换一个串口调试助手软件。 上面这个就是我换了的软件 在开发的时候&#xff0c;经常会遇到软件故障&#xff0c;导致正确的方法&#xff0c;但是没有效果&#xff0c;好比以前用盗版的8.7版本的Proteus模拟…

Leetcode2760. 最长奇偶子数组

Every day a Leetcode 题目来源&#xff1a;2760. 最长奇偶子数组 解法1&#xff1a;模拟 代码&#xff1a; class Solution { public:int longestAlternatingSubarray(vector<int> &nums, int threshold){int n nums.size();int ans 0;for (int i 0; i <…

vue3基础学习(上)

##以前怎么玩的? ###MVC Model:Bean View:视图 Controller ##vue的ref reactive ref:必须是简单类型 reactive:必须不能是简单类型 ###创建一个Vue项目 npm init vuelatest ###生命周期 ###setup相关 ####Vue2的一些写法 -- options API ####Vue3的写法 组合式API Vu…

Elasticsearch基础增删改查

Elasticsearch是面向文档型数据库&#xff0c;一条数据在这里就是一个文档 倒排索引 正排(正向)索引&#xff1a; IDcontent01my name is zhangsan02my name is lisi 倒排索引&#xff1a; keywordIDname01,02zhang01 创建索引 创建索引等同于创建数据库 PUT具有幂等性&…

sqlserver配置管理器无法启动解决方案

在SQL server configuration manager配置管理器中遇到SQL server browser呈灰色&#xff0c;无法启动 右击选择属性 进入服务 将启动模式改为自动 可以启动了

Python大语言模型实战-利用MetaGPT框架自动开发一个游戏软件(附完整教程)

实现功能 MetaGPT是一个应用在软件开发领域的多智能体框架&#xff0c;其主要创新点在于将SOP标准流水线和Agent结合在了一起&#xff0c;使得拥有不同技能的Role之间配合完成一项较为复杂的任务。本文将用一个案例来演示整个流程。 实现代码 项目地址&#xff1a;https://gi…

3DMAX各种拼图建模插件集锦之“彩虹系列”

现实生活中我们随处可见各种重复的图案&#xff0c;例如地面上铺设的地砖&#xff0c;砌的砖墙石墙&#xff0c;覆盖着瓦片的屋顶&#xff0c;用作装饰的拼图图案等等&#xff0c;这些重复的拼图单体建模看似简单&#xff0c;但是大面积铺设&#xff0c;如果完全手动就有些费时…

FPGA——IP核 基础操作

FPGA——IP核 基础操作 IP核例化模块时钟IP核RAM IP核 IP核例化模块 找到模版 加入代码中 时钟IP核 配置模式功能 配置输入时钟 输出配置 RAM IP核

NSS [SWPUCTF 2022 新生赛]1z_unserialize

NSS [SWPUCTF 2022 新生赛]1z_unserialize 我敲&#xff0c;报恩题&#xff01; 直接用构造方法构造POC更改$lt和$lly <?php class lyh{public $lt;public $lly;function __construct(){$this->lt"system";$this->lly"tac /flag";} } $a new…

图片转换成base64格式的优缺点

文章目录 前言什么是base64? 一&#xff0c;优点二&#xff0c;缺点三&#xff0c;工具 前言 什么是base64? Base64&#xff0c;顾名思义&#xff0c;就是包括小写字母a-z、大写字母A-Z、数字0-9、符号"“、”/“一共64个字符的字符集&#xff0c;&#xff08;另加一个…