百度百科:https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E6%A0%91/2305769?fr=aladdin
------------------------------------------------------------------------------------------------
例如:频率表 A:60, B:45, C:13 D:69 E:14 F:5 G:3
第一步:找出字符中最小的两个,小的在左边,大的在右边,组成二叉树。在频率表中删除此次找到的两个数,并加入此次最小两个数的频率和。
F和G最小,因此如图,从字符串频率计数中删除F与G,并返回G与F的和 8给频率表
重复第一步:
-------------------------------------------------------------------------------------------------
频率表 A:60, B:45, C:13 D:69 E:14 FG:8
最小的是 FG:8与C:13,因此如图,并返回FGC的和:21给频率表。
---------------------------------------------------------------------------------------------------
重复第一步:
---------------------------------------------------------------------------------------------------
频率表 A:60 B: 45 D: 69 E: 14 FGC: 21
如图
-----------------------------------------------------------------------------------------------------
重复第一步
-----------------------------------------------------------------------------------------------------
频率表 A:60 B: 45 D: 69 FGCE: 35
-----------------------------------------------------------------------------------------------------
重复第一步
-----------------------------------------------------------------------------------------------------
频率表 A:60 D: 69 FGCEB: 80
-----------------------------------------------------------------------------------------------------
重复第一步
-----------------------------------------------------------------------------------------------------
频率表 AD:129 FGCEB: 80
添加 0 和 1,规则左0 右1
频率表 A:60, B:45, C:13 D:69 E:14 F:5 G:3
每个 字符 的 二进制编码 为(从根节点 数到对应的叶子节点,路径上的值拼接起来就是叶子节点字母的应该的编码)
A:10
B:01
C:0011
D:11
E:000
F:00101
G:00100
那么当我想传送 ABC时,编码为 10 01 0011
补充一下白话版:
大家观察 出现得越多的字母,他的编码越短 ,出现频率越少的字母,他的编码越长。
在信息传输过程中,如果这个字母越多,那么我们希望他越瘦小(编码短)这样占用的编码越少,其实编码长的字母也是让频率比它多的字母把编码短的位子都占用后,他才去占用当前最短的编码。至此让总的编码长度最短。
且要保证长编码的不与短编码的字母冲突:
比如 不能出现 读码 读到 01 还有长编码的 字母为011,如果短编码为一个长编码的左起子串,这就是冲突,意思就是说读到当前位置已经能确定是什么字母时不能因为再读取一位或几位让这个编码能表示另外的字母,
但哈夫曼树(最优二叉树)在构造的时候就避免了这个问题。为什么能避免呢,因为哈夫曼树的它的字母都在叶子节点上,因此不会出现一个字母的编码为另一个字母编码左起子串的情况。
----原文补充----
我再补充一下:
冲突情况:如果我们已经确定D,E,F,G 用 01 ,010 ,10,001的2进制编码来传输了。那么想传送FED时,我需要传送1001001,接收方可以把它解析为FDG,当然也能解析为FED,他两编码一样的,这就是编码冲突,显然这是不行的,就像我说压脉带,你如果是日本人会理解为 (你懂得),这就是发出同一种语,得出不同的意的情况。所以不能让一个字母的二进制代表数,为另一个字母的二进制代表数的子串。但为什么实际要求只是左起子串呢而不是绝对意义上的子串呢,因为计算机从数字串的左边开始读,如果从右边读,那么可以是右起(无奈)。你又可以问了为什么是左起或右起不直接规定不能是子串呢,比如说原文中B就是C,F,G的子串,那这不就不符合规则了么。这里是为了哈夫曼的根本目的,优化编码位占用问题,如果完全不能有任何子串那么编码将会非常庞大。但这里计算机是一位一位的·读取编码的,只需要保证计算机在读取中不会误判就行。并且编码占用最少。
因为哈夫曼是从叶子节点开始构造构造到根节点的,而且构造时,都是计算两个权值的节点的和再与其他叶子节点再生成一个父节点来组成一个新的树。并且不允许任何带有权值的节点作为他们的父节点。这也保证了所有带有权值的节点都被构造为了叶子节点。然后最后编码的时候是从根节点开始走到叶子节点而得出的编码。在有权值的节点又不会出现在任何一条路的路途中的情况,只会出现在终点的情况下,因此不会出现01代表一个字母011又代表一个字母。
又如原文ABC编码为10010011的情况,当计算机读到10时,由于有左起子串不冲突的原则。那么计算机完全可以保证当前的10就是A字母,然后再往下读010011的部分,然后当读到01时,也完全能确定B,C同理,而不用说因为会出现冲突的编码而接着继续读取之后的编码来确定前面的编码。这样对信息的判断和效率是相当的不利的,也不是说不可以。即使你ABCD,分别用01,011,0111,01111来代替也行,传输后也能精确识别,但是数据量极大呢,想代替整个中文编码呢,那0后面得多少个1才能代表完。因此哈夫曼就是为了获得最少编码量代替最多字符串,并且不冲突,系统不会误判而产生的。
----原文补充end----
看懂的朋友留个赞,没看懂的留言我给你单独讲 _(:з」∠)_