这个问题原始是用来实现一个可变长度的编码问题,但可以总结成这样一个问题,假设我们有很多的叶子节点,每个节点都有一个权值w(可以是任何有意义的数值,比如它出现的概率),我们要用这些叶子节点构造一棵树,那么每个叶子节点就有一个深度d,我们的目标是使得所有叶子节点的权值与深度的乘积之和$$\Sigma w{i}d{i}$$最小。

很自然的一个想法就是,对于权值大的叶子节点我们让它的深度小些(更加靠近根节点),权值小的让它的深度相对大些,这样的话我们自然就会想着每次取当前权值最小的两个节点将它们组合出一个父节点,一直这样组合下去直到只有一个节点即根节点为止。如下图所示的示例

代码实现比较简单,使用了heapq模块,树结构是用list来保存的,有意思的是其中zip函数的使用,其中统计函数count作为zip函数的参数,

代码实现比较简单,使用了heapq模块,树结构是用list来保存的,有意思的是其中zip函数的使用,其中统计函数count作为zip函数的参数,

from heapq importheapify, heappush, heappopfrom itertools importcountdefhuffman(seq, frq):

num=count()

trees= list(zip(frq, num, seq)) #num ensures valid ordering

heapify(trees) #A min-heap based on freq

while len(trees) > 1: #Until all are combined

fa, _, a = heappop(trees) #Get the two smallest trees

fb, _, b =heappop(trees)

n=next(num)

heappush(trees, (fa+fb, n, [a, b])) #Combine and re-add them

#print trees

return trees[0][-1]

seq= "abcdefghi"frq= [4, 5, 6, 9, 11, 12, 15, 16, 20]printhuffman(seq, frq)#[['i', [['a', 'b'], 'e']], [['f', 'g'], [['c', 'd'], 'h']]]

现在我们考虑另外一个问题,合并文件问题,假设我们将大小为 m 和大小为 n 的两个文件合并在一起需要 m+n 的时间,现在给定一些文件,求一个最优的合并策略使得所需要的时间最小。

如果我们将上面哈夫曼树中的叶子节点看成是文件,两个文件合并得到的大文件就是树中的内部节点,假设每个节点上都有一个值表示该文件的大小,合并得到的大文件上的值是合并的两个文件的值之和,那我们的目标是就是使得内部节点的和最小的合并方案,因为叶子节点的大小是固定的,所以实际上也就是使得所有节点的和最小的合并方案!

细想也就有了一个叶子节点的所有祖先节点们都有一份该叶子节点的值包含在里面,也就是说所有叶子节点的深度与它的值的乘积之和就是所有节点的值之和!可以看下下面的示例图,最终我们知道哈夫曼树就是这个问题的解决方案。

哈夫曼树问题的一个扩展就是最优二叉搜索树问题,后者可以用动态规划算法来求解

其他实现方式:

#Huffman Encoding

#Tree-Node Type

classNode:def __init__(self,freq):

self.left=None

self.right=None

self.father=None

self.freq=freqdefisLeft(self):return self.father.left ==self#create nodes创建叶子节点

defcreateNodes(freqs):return [Node(freq) for freq infreqs]#create Huffman-Tree创建Huffman树

defcreateHuffmanTree(nodes):

queue=nodes[:]while len(queue) > 1:

queue.sort(key=lambdaitem:item.freq)

node_left=queue.pop(0)

node_right=queue.pop(0)

node_father= Node(node_left.freq +node_right.freq)

node_father.left=node_left

node_father.right=node_right

node_left.father=node_father

node_right.father=node_father

queue.append(node_father)

queue[0].father=Nonereturnqueue[0]#Huffman编码

defhuffmanEncoding(nodes,root):

codes= [''] *len(nodes)for i inrange(len(nodes)):

node_tmp=nodes[i]while node_tmp !=root:ifnode_tmp.isLeft():

codes[i]= '0' +codes[i]else:

codes[i]= '1' +codes[i]

node_tmp=node_tmp.fatherreturncodesif __name__ == '__main__':#chars = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N']

#freqs = [10,4,2,5,3,4,2,6,4,4,3,7,9,6]

chars_freqs = [('C', 2), ('G', 2), ('E', 3), ('K', 3), ('B', 4),

('F', 4), ('I', 4), ('J', 4), ('D', 5), ('H', 6),

('N', 6), ('L', 7), ('M', 9), ('A', 10)]

nodes= createNodes([item[1] for item inchars_freqs])

root=createHuffmanTree(nodes)

codes=huffmanEncoding(nodes,root)for item inzip(chars_freqs,codes):print 'Character:%s freq:%-2d encoding: %s' % (item[0][0],item[0][1],item[1])

输出结果:

>>>Character:C freq:2 encoding: 10100Character:G freq:2 encoding: 10101Character:E freq:3 encoding: 0000Character:K freq:3 encoding: 0001Character:B freq:4 encoding: 0100Character:F freq:4 encoding: 0101Character:I freq:4 encoding: 0110Character:J freq:4 encoding: 0111Character:D freq:5 encoding: 1011Character:H freq:6 encoding: 1110Character:N freq:6 encoding: 1111Character:L freq:7 encoding: 001Character:M freq:9 encoding: 100Character:A freq:10 encoding: 110

python哈夫曼编码注意_Python 算法(2) 哈夫曼编码 Huffman Encoding相关推荐

  1. python的字符编码叙述_Python: 熟悉又陌生的字符编码

    字符编码是计算机编程中不可回避的问题,不管你用 Python2 还是 Python3,亦或是 C++, Java 等,我都觉得非常有必要厘清计算机中的字符编码概念.本文主要分以下几个部分介绍: 基本概 ...

  2. python基础编码规范_Python语言的基本语法和编码规范.doc

    Python 语言的基本语法和编码规范 Python 编程教程教师 : 工作 :Python 语言的基本语法和编码标 准课程描述本章将介绍 Python 语言的基本语法和编码标准,重点介 绍 Pyth ...

  3. python的栈在哪个库_Python算法实战系列之栈

    栈(stack)又称之为堆栈是一个特殊的有序表,其插入和删除操作都在栈顶进行操作,并且按照先进后出,后进先出的规则进行运作. 如下图所示 例如枪的弹匣,第一颗放进弹匣的子弹反而在发射出去的时候是最后一 ...

  4. python 3.x版本的默认编码是_Python 3.x默认使用的编码是_

    Python 3.x默认使用的编码是_ 答:UTF-8 X 线平片正常肺门阴影的最主要解剖结构是 答:肺动脉 . 肺静脉 <春秋>属于"六籍"之一.() 答:√ 中国大 ...

  5. python同时满足两个条件_python算法-快速寻找满足条件的两个数

    题目前提是一定存在这样两个数 解法一就不写了...一般想不到吧 一开始想到的是解法二最后的用hash表 (其实是想到创建一个跟target一样大的数组啦..存在就写入index,但是要全部找出,那得二 ...

  6. 【数据结构与算法】-哈夫曼树(Huffman Tree)与哈夫曼编码

    超详细讲解哈夫曼树(Huffman Tree)以及哈夫曼编码的构造原理.方法,并用代码实现. 1哈夫曼树基本概念 路径:从树中一个结点到另一个结点之间的分支构成这两个结点间的路径. 结点的路径长度:两 ...

  7. 贪心算法-03哈夫曼编码问题

    哈夫曼编码 简介 哈夫曼编码是一种字符编码方式,可以对指定的字符集进行数据压缩,压缩率在20%到90%. 问题描述 现在有一个包含5个字符{A,B,C,D,E},各个字符的出现频率依次为{0.35, ...

  8. 算法导论——贪心算法:哈夫曼编码(霍夫曼编码)

    2019独角兽企业重金招聘Python工程师标准>>> package org.loda.greedy;import org.junit.Test; import org.loda. ...

  9. 哈夫曼算法证明+哈夫曼编码译码程序实现

    哈夫曼算法证明 哈夫曼算法是一种贪心算法,我们考虑证明其最优子结构和贪心选择性质: 最优子结构:假设一个树是哈夫曼树,则以其任意节点为根节点的最大子树也是哈夫曼树. 证明:子树的根节点的值是其所有叶子 ...

最新文章

  1. pku 3422 Kaka's Matrix Travels 最大费用最大流
  2. Python相关机器学习‘武器库’
  3. python全栈开发 * 14 知识点汇总 * 180530
  4. jstl java_JSTL-Java-Baby-51CTO博客
  5. C++回声服务器_4-UDP connect版本客户端
  6. ruby中的self
  7. 【英语学习】【WOTD】countermand 释义/词源/示例
  8. 微型计算机系统的主存储器,微型计算机系统中 ,操作系统保存在硬盘上,其主存储器应该采用 ( )...
  9. 基于汇编的 C/C++ 协程 - 背景知识
  10. matlab 文本分析工具,MATLAB,Simulink. - Text Analytics , 文本分析工具箱-鈦思科技
  11. filenet java配置_技术的力量:IPFS新贵Filenet缘何采用Podt
  12. 视频格式怎么改为mp4?有什么好用的视频格式转换软件
  13. 计算机无法找到wifi,笔记本无线网络找不到,教您怎么解决笔记本找不到无线网络...
  14. mysql免安装版设置开机启动
  15. python实现增删改查电话本程序笔记
  16. InDesign: Interactive PDFs InDesign交互式PDF文件教程 Lynda课程中文字幕
  17. 英语学习APP—百词斩
  18. 非专业人士对特斯拉人工智能日的专业解释 ——记@Cosmacelf在Reddit.com上对于AI Day的评价...
  19. Compound 治理——提案
  20. Libra最大的竞争对手是什么?Calibra高管给出答案

热门文章

  1. python降维将多列数据压缩为一列_Python机器学习(Sebastian著 ) 学习笔记——第五章通过降维压缩数据(Windows Spyder Python 3.6)...
  2. android 仿微信选取相册_Android 仿微信 相册多图选择器
  3. 华为荣耀20和x10比较_荣耀x10和荣耀20Pro哪个值得入手 荣耀x10和荣耀20Pro参数对比...
  4. busybox arm-linux-gcc 4.4.4库的路径,BUSYBOX编译错误及解决方法总结
  5. 太赞了!用200道题彻底搞定Python数据处理!
  6. 你已经是个成熟的985大学了,请不要在大一教 C 语言!
  7. 如何将 Pycharm 打造得更称手
  8. 屏幕滑动_Appium滑动引导页swipe函数
  9. android 程序类图,Android模板设计模式之 - 构建整个应用的BaseActivity
  10. 机器学习(数据挖掘十个重要算法)