哈夫曼编码详细证明步骤

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

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

这里写目录标题

  • 一:编码
    • 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.rhkb.cn/news/194441.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

langchain(1):使用LangChain 调用 openai 的 text/chat model

文章目录 重要参考OPENAI API调用 Text 模型调用 Chat 模型消息角色 Chat 模型 vs Text 模型 通过 LangChain 调用 Text 和 Chat 模型调用 text 模型调用 chat 模型 重要参考 langchain 中文网 langchain api openai api 文档 huggingface LangChain 是一个全方位的、基于大…

中国芯片金字塔成形,商业化拐点将至

其作始也简&#xff0c;其将毕也钜。 传说埃及用时30年建成左赛尔金字塔&#xff0c;成为亘古不灭的世界奇迹。在今天&#xff0c;中国芯片产业走过8年“国产替代”历程&#xff0c;国产芯片的“金字塔”体系业已初具雏形&#xff0c;展现出蓬勃的发展潜力。 2023年是补全自主…

c++ 经典服务器开源项目Tinywebserver如何运行

第一次直接按作者的指示&#xff0c;运行sh ./build.sh,再运行./server&#xff0c;发现不起作用&#xff0c;localhost:9006也是拒绝访问的状态&#xff0c;后来摸索成功了发现&#xff0c;运行./server之后&#xff0c;应该是启动状态&#xff0c;就是不会退出&#xff0c;而…

计算机视觉基础(8)——齐次坐标系与相机内外参

前言 本节我们将学习到透视投影、齐次坐标系等基础知识&#xff0c;在这些基础知识上&#xff0c;进一步了解到相机的参数&#xff0c;相机参数分为相机外参和相机内参&#xff0c;相机外参是从世界坐标系到相机坐标系&#xff0c;相机内参是从相机坐标系到图像坐标系。 一、透…

成功解决:com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl.

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 前言 使用Spring 整合 mybatis的时候 报错…

k8s_base

应用程序在服务器上部署方式的演变,互联网发展到现在为止 应用程序在服务器上部署方式 历经了3个时代1. 传统部署 优点简单 缺点就是操作系统的资源是有限制的&#xff0c;比如说操作系统的磁盘&#xff0c;内存 比如说我8G&#xff0c;部署了3个应用程序&#xff0c;当有一天…

Django测试环境搭建及ORM查询(创建外键|跨表查询|双下划线查询 )

文章目录 一、表查询数据准备及测试环境搭建模型层前期准备测试环境搭建代码演示 二、ORM操作相关方法三、ORM常见的查询关键字四、ORM底层SQL语句五、双下划线查询数据查询&#xff08;双下划线&#xff09;双下划线小训练Django ORM __双下划线细解 六、ORM外键字段创建基础表…

国内领先的五大API接口供应商

API&#xff08;Application Programming Interface&#xff09;接口&#xff0c;现在很多应用系统中常用的开放接口&#xff0c;对接相应的系统、软件功能&#xff0c;简化专业化的程序开发。作者用过的国内比较稳定的API接口供应商有如下几家&#xff0c;大家可以参考选择&am…

苍穹外卖-day11

苍穹外卖-day11 课程内容 Apache ECharts营业额统计用户统计订单统计销量排名Top10 功能实现&#xff1a;数据统计 数据统计效果图&#xff1a; 1. Apache ECharts 1.1 介绍 Apache ECharts 是一款基于 Javascript 的数据可视化图表库&#xff0c;提供直观&#xff0c;生…

调整Windows键盘上只能看到拼音而无法看到实际的文本以及关闭输入法悬浮窗方法

一、输入法设置 如果您在键盘上只能看到拼音而无法看到实际的文本&#xff0c;这可能是因为您的输入法设置为中文拼音输入法或其他仅显示拼音的输入法。 要解决这个问题&#xff0c;您可以尝试以下方法&#xff1a; 1. 切换输入法&#xff1a;按下 Shift Alt 组合键或 Wind…

轻量封装WebGPU渲染系统示例<27>- 浮点RTT纹理(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/FloatRTT.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: const floatRTT { diffuse: { uuid: "rtt0", rttTe…

2023年亚太杯数学建模思路 - 案例:ID3-决策树分类算法

文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模…

Backblaze 2023 Q3硬盘故障质量报告解读

作为一家在2021年在美国纳斯达克上市的云端备份公司&#xff0c;Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告&#xff0c;给大家提供了一份真实应用场景下的稳定性分析参考数据。2023年度之前发布的两次报告&#xff0c;请参考&#xff1a; Backblaze发布2…

qnx 工程目录创建工具 addvariant

文章目录 前言一、addvariant 是什么二、addvariant 使用实例1. variant names 参数说明2. 创建一个可执行文件工程3. 创建一个动态库工程 总结参考资料 前言 本文主要介绍如何在qnx 开发环境中创建工程目录及其相关的配置文件(common.mk, Makefile 文件等) 软件版本&#xff…

Java毕业设计心得体会

1. 开始准备选题、开题报告 大四上学期开学时开始准备论文的&#xff0c;首先是确定论文主题&#xff0c;看自己想做什么毕业设计&#xff0c;可以选取之前接触过的&#xff0c;做过的东西&#xff0c;这样快一些&#xff0c;我之前一直是学Java的&#xff0c;就打算直接用Jav…

如何将本地Portainer管理界面结合cpolar内网穿透工具实现远程浏览器访问

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

操作系统(二 )| 进程控制 进程状态 进程描述 进程控制 进程同步互斥

文章目录 1 进程和程序区别2 进程状态2.1 进程的5种基本状态2.2 进程状态之间转换2.3 七状态模型 3 进程描述3.1 进程控制块 PCB3.2 进程块组织方式 4 进程控制5 进程同步 互斥5.1 区分进程互斥和同步5.2 核心方案5.3 其他方案方案1 设置锁变量方案2 严格轮转法方案3 Peterson解…

rabbitmq 集群搭建

RabbitMQ集群介绍 RabbitMQ集群是一组RabbitMQ节点&#xff08;broker&#xff09;的集合&#xff0c;它们一起工作以提供高可用性和可伸缩性服务。 RabbitMQ集群中的节点可以在同一物理服务器或不同的物理服务器上运行。 RabbitMQ集群的工作原理是&#xff0c;每个节点在一个…

【机器学习】K近邻算法:原理、实例应用(红酒分类预测)

案例简介&#xff1a;有178个红酒样本&#xff0c;每一款红酒含有13项特征参数&#xff0c;如镁、脯氨酸含量&#xff0c;红酒根据这些特征参数被分成3类。要求是任意输入一组红酒的特征参数&#xff0c;模型需预测出该红酒属于哪一类。 1. K近邻算法介绍 1.1 算法原理 原理&a…

Spring cloud负载均衡@LoadBalanced LoadBalancerClient

LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…