HuffmanTree的python实现 – 潘登同学的图论笔记

文章目录

    • HuffmanTree的python实现 -- 潘登同学的图论笔记
  • 哈夫曼树
    • 构建哈夫曼树的过程
  • 树节点实现
  • HuffmanTree实现
  • 绘制HuffmanTree
    • 测试代码

哈夫曼树

当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,

在构建哈弗曼树时,要使树的带权路径长度最小,只需要遵循一个原则,那就是:权重越大的结点离树根越近。在图 1 中,因为结点 a 的权值最大,所以理应直接作为根结点的孩子结点。

构建哈夫曼树的过程

  1. 在 n 个权值中选出两个最小的权值,对应的两个结点组成一个新的二叉树,且新二叉树的根结点的权值为左右孩子权值的和
  2. 在原有的 n 个权值中删除那两个最小的权值,同时将新的权值加入到 n–2 个权值的行列中,以此类推
  3. 重复 1 和 2 ,直到所以的结点构建成了一棵二叉树为止,这棵树就是哈夫曼树

话不多说,直接看代码

树节点实现

树节点基本上都是大同小异的

  • root: 该节点是否为叶节点(不是则为None)
  • value: 记录这个词
  • frq: 记录这个词出现的频次(或者是某个父节点下所有frq之和)
  • size: 记录这个某个父节点下的节点总数(主要用于画图)
class HuffmanTreeNode:def __init__(self,root=None,value:str=None,frq:int=0,) -> None:self.root=rootself.value = valueself.frq = frqself.left = Noneself.right = Noneself.size = 1def Setleft(self,left):self.left = leftself.frq += left.Getfrq()self.size += left.GetSize()return selfdef Setright(self,right):self.right = rightself.frq += right.Getfrq()self.size += right.GetSize()return selfdef Getfrq(self):return self.frqdef Getvalue(self):return self.valuedef GetSize(self):return self.sizedef Hasright(self):return self.rightdef Hasleft(self):return self.leftdef Isroot(self):return self.rootdef __str__(self) -> str:if self.root:return f'root, sum of frequency:{self.frq}'else:return f'value: {self.value}, frequency: {self.frq}'

HuffmanTree实现

HuffmanTree主要有两个方法

  • _buildHuffmanTree: 将词频字典输入,进行树的构建
  • _iter_node: 在构建好的树中,获得某个词的编码(因为哈夫曼树就是用于解决编码的,但是后来有很多的作用,我就是从CBOW模型过来的)
class HuffmanTree:def __init__(self,num:dict) -> None:# 对字典按照其values进行排序self.num = sorted(num.items(),key=lambda x:x[1],reverse=False)self.list = []  # 一个储存列表self.coding = {} # 编码结果self._buildHuffmanTree()self._iter_node(self.list[0])def _buildHuffmanTree(self):self.list = [HuffmanTreeNode(root=False,value=i[0],frq=i[1]) for i in self.num]while len(self.list) > 1:# 将两个小的节点合并  小的放左边right_node = self.list[1]left_node = self.list[0]# 注意pop顺序self.list.pop(1)self.list.pop(0)temp_node = HuffmanTreeNode(root=True)temp_node.Setright(right_node)temp_node.Setleft(left_node)# 将合并后的根节点放回list中if len(self.list) == 1:if temp_node.Getfrq() < self.list[0].Getfrq():self.list.insert(0,temp_node)else:self.list.insert(1,temp_node)elif len(self.list) == 0:self.list.insert(0,temp_node)else:for i in range(len(self.list)-1):if i == 0 and temp_node.Getfrq() <= self.list[i].Getfrq():self.list.insert(i,temp_node)continueelif self.list[i].Getfrq() < temp_node.Getfrq() <= self.list[i+1].Getfrq():self.list.insert(i+1,temp_node)continueelif i == len(self.list)-2 and temp_node.Getfrq() > self.list[i+1].Getfrq():self.list.insert(i+2,temp_node)continuedef getTree(self):return self.list[0]def _iter_node(self,node,code=''):if node:if not node.Isroot():self.coding[node.Getvalue()] = codeself._iter_node(node.Hasleft(),code='0'+code)self._iter_node(node.Hasright(),code='1'+code)def getCode(self):return self.coding

绘制HuffmanTree

画图函数与之前画红黑树的区别不大,改一改拿来用就行

class Draw_RBTree:def __init__(self, tree):self.tree = treedef show_node(self, node, ax, height, index, font_size):if not node:returnx1, y1 = None, Noneif node.left:x1, y1, index = self.show_node(node.left, ax, height-1, index, font_size)x = 100 * index - 50y = 100 * height - 50if x1:plt.plot((x1, x), (y1, y), linewidth=2.0,color='b')circle_color = 'mediumspringgreen'text_color = 'black'ax.add_artist(plt.Circle((x, y), 50, color=circle_color))text = str(node.Getfrq()) if node.Isroot() else node.Getvalue() + '\n' + str(node.Getfrq())ax.add_artist(plt.Text(x, y, text, color= text_color, fontsize=font_size, horizontalalignment="center",verticalalignment="center"))# print(str(node.val), (height, index))index += 1if node.right:x1, y1, index = self.show_node(node.right, ax, height-1, index, font_size)plt.plot((x1, x), (y1, y), linewidth=2.0, color='b')return x, y, indexdef show_hf_tree(self, title):fig = plt.figure(figsize=(10,6))ax = fig.add_subplot(111)left, right = self.get_left_length(), self.get_right_length(), height = 2 * np.log2(self.tree.size + 1)# print(left, right, height)plt.ylim(0, height*100 + 50)plt.xlim(0, 100 * self.tree.size + 100)self.show_node(self.tree, ax, height, 1, self.get_fontsize())plt.axis('off')plt.title(title)plt.show()def get_left_length(self):temp = self.treelen = 1while temp:temp = temp.leftlen += 1return lendef get_right_length(self):temp = self.treelen = 1while temp:temp = temp.rightlen += 1return lendef get_fontsize(self):count = self.tree.sizeif count < 10:return 30if count < 20:return 20return 16

测试代码

if __name__ == '__main__':num = {'a':10,'b':15,'c':12,'d':3,'e':4,'f':13,'g':1}h = HuffmanTree(num)tree = h.getTree()d = Draw_RBTree(tree)d.show_hf_tree('HuffmanTree')print(h.getCode())

哈夫曼树python实现相关推荐

  1. 哈夫曼树(Huffman Tree)的介绍、画法、哈夫曼树的可视化显示(Python代码实现)

    https://blog.csdn.net/hanhanwanghaha宝藏女孩 欢迎您的关注! 欢迎关注微信公众号:宝藏女孩的成长日记 如有转载,请注明出处(如不注明,盗者必究) 目录 一.概念 二 ...

  2. Python实现霍夫曼树

    Python实现霍夫曼树 霍夫曼树是一种特殊的二叉树,是一种带权路径长度最短的二叉树,又称为最优二叉树. 给定 N 个权值作为二叉树的 N 个叶节点的权值,构造一棵二叉树,若该二叉树的带权路径长度达到 ...

  3. python实现哈夫曼树的可视化

    标题 1,允许转载,只需在该博客下的评论下评论,并附上自己的博客地址即可 2,不允许伪原创 3,其他暂议 1.配置pip安装工具 在python的文件下找到script文件夹 打开文件夹Scripts ...

  4. Python数据结构11:树的实现,树的应用,前中后序遍历,二叉查找树BST,平衡二叉树AVL树,哈夫曼树和哈夫曼编码

    1.概念 树一种基本的"非线性"数据结构. 相关术语: 节点Node:组成树的基本部分.每个节点具有名称,或"键值",节点还可以保存额外数据项,数据项根据不同的 ...

  5. Huffman Tree哈夫曼树权值路径长度WPL计算,binarytree ,Python

    Huffman Tree哈夫曼树(霍夫曼树.赫夫曼树)权值路径长度WPL计算,binarytree ,Python 计算定义:把构建成功的哈夫曼树的每一个边缘节点(叶子)值乘以该节点到根的路径长度,最 ...

  6. python哈夫曼树_python霍夫曼树

    class Node(): data=0 left=None right=None father=None def __init__(self,data,left,right): self.data= ...

  7. Huffman哈夫曼树编码字符,binarytree,Python

    Huffman哈夫曼树(霍夫曼树,赫夫曼树)在通信领域最主要的应用是数据编码.假设现在有A.B.C.D.E五个字符,它们出现的概率或者权值不同,从A到E,权值依次降低,那么就可以用哈夫曼最优二叉树对其 ...

  8. 怎么用python实现哈夫曼树_数据结构-哈夫曼树(python实现)

    好,前面我们介绍了一般二叉树.完全二叉树.满二叉树,这篇文章呢,我们要介绍的是哈夫曼树. 哈夫曼树也叫最优二叉树,与哈夫曼树相关的概念还有哈夫曼编码,这两者其实是相同的.哈夫曼编码是哈夫曼在1952年 ...

  9. Python---哈夫曼树---Huffman Tree

    今天要讲的是天才哈夫曼的哈夫曼编码,这是树形数据结构的一个典型应用. !!!敲黑板!!!哈夫曼树的构建以及编码方式将是我们的学习重点. 老方式,代码+解释,手把手教你Python完成哈夫曼编码的全过程 ...

最新文章

  1. 安装软件要求输入服务器配置信息,信息技术考试软件配置安装与操作规范(管理服务端与客户端)(30页)-原创力文档...
  2. C++:53---菱形继承、虚继承
  3. linux常用命令 打开文件,【Linux】常用命令 lsof查看打开的文件
  4. swift mvvm_Swift中的MVVM设计模式概述
  5. blender 3d打印_使用Blender和Python 3D打印连衣裙
  6. 学习C++就这么简单
  7. Oracle11g数据库审计功能的关闭和开启
  8. 高速公路的一些线路计算
  9. SSD算法详解 及其 keras实现
  10. 基于JAVA高铁在线购票系统计算机毕业设计源码+数据库+lw文档+系统+部署
  11. linux ld so 源码分析,ld.so分析2
  12. CreateJS 指南
  13. mac网易云音乐,脚本实现睡眠功能
  14. Python学习工具第五期 — 免费使用,无须激活下载安装Pycharm教程
  15. Github网站css加载不出来的处理方法
  16. 杭州安川焊接机器人_安川YASKAWA 焊接机器人MA1400
  17. adobe acrobat reader保存至原路径不用选择路径不覆盖
  18. 万年历首页效果android,简约好用的日历APP
  19. 织梦二次开发简单mvc例子
  20. 记录一下在浏览器端利用微信地图定位接口和百度地图定位接口实现高精度定位的开发心得

热门文章

  1. 深入浅出,聊聊实时音视频中的回声消除与降噪
  2. Windows程序员与Makefile的情缘
  3. ffmpeg 直接将m3u8转成mp4
  4. 【数学期望】期望dp
  5. 激烈赛程预告!原来你是这样的大赛
  6. 如何申请使用 Copilot
  7. 日本最受欢迎人工智能竟是女子高中生
  8. java-Stream.reduce()在实际开发中的应用
  9. TOTP动态令牌(基于openssl/HAMC)
  10. 怎样使用CSS设置文字与文字间距距离?