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. 在IIS8.5的环境下配置WCF的Restful Service
  2. 基于maven使用IDEA创建多模块项目
  3. 【响应式Web前端设计】HTML DOM padding 属性
  4. 杭电2855 Fibonacci Check-up
  5. Bengio等人新作:基于双层规划的端到端分子构象生成框架
  6. NeurIPS2021 HRFormer:HRNet又出续作啦!国科大北大MSRA提出高分辨率Transformer,开源!...
  7. Citrix小贴纸---连接XenAPP时协议驱动程序错误
  8. 发现 nios2-elf-gcc 一处 bug
  9. 软考高级 真题 2016年下半年 信息系统项目管理师 综合知识
  10. 慧荣SM2258XT主控固态硬盘B05 B16 B17闪存开卡步骤
  11. ftp扫描工具下载,ftp扫描下载工具到底该怎么选择?
  12. Scratch(二十六):小兔子乖乖
  13. Oracle10g卡顿,192MB内存运行win10 系统启动大约3分钟响应非常慢
  14. 列表表达式爬取红牛分公司数据
  15. 移臂调度算法java_C语言 磁盘调度模拟
  16. GOM引擎单机架设配置教程
  17. 即构组局:线上娃娃机的这几个月,都经历了些什么?
  18. ubuntu系统下mysql数据库的备份与恢复
  19. cloudreve使用nginx反向代理时上传卡死或速度慢的解决办法
  20. OpenCV4学习笔记(58)——二维码检测与识别

热门文章

  1. OpenCASCADE BRep vs. OpenNURBS BRep
  2. (精简稳定版)win8系统下装win7系统
  3. 超分辨率重建学习总结、SR、super resolution、single image super resolution
  4. [cc150] 1.2
  5. 到底什么是谱聚类算法?
  6. 解决WIFI驱动RTL8188无法在rk3168平板Android4.2启动wifi的问题
  7. C语言之联合(union)的妙用
  8. 拥有Low-code源代码对程序有哪些作用?
  9. 学习IT编程必看的资源介绍
  10. 叉乘与反对称矩阵(以i,j,k为基然后写成反对称矩阵与向量相称的形式)[w]_x