当前位置: 首页 > news >正文

【14】数据结构之哈夫曼树篇章

目录标题

  • 哈夫曼树
    • 哈夫曼树的定义
    • 哈夫曼树的构造
    • 哈夫曼编码
    • 哈夫曼树的实现

哈夫曼树

哈夫曼树的定义

  • 路径:从一个结点到另一个结点的路线
  • 树的路径长度:从树根到树中每个结点的路径长度之和
  • 结点的权:在一些应用中,赋予树中结点的一个有某种意义的实数
  • 结点的带权路径长度:结点到树根之间的路径长度与该结点权值的乘积
  • 树的带权路径长度WPL:树中所有叶子结点的带权路径长度之和 WPL = ∑ i = 1 n w i l i \text{WPL} = \sum_{i=1}^{n} w_i l_i WPL=i=1nwili
  • 其中,w是叶子结点的权值,n是叶子结点的个数,l是叶子结点到根的路径长度.
  • 带权路径长度最小的二叉树称为最优二叉树.

哈夫曼树的构造

  • 有n棵权值分别为w₁, w₂, …, wₙ的二叉树所组成的集合,这些二叉树的左右子树都为空
  • 从集合中选取出权值最小的两棵二叉树构成一棵新的二叉树。为了保证新树仍是二叉树,需要增加一个新结点作为新二叉树的根,将所选的两棵子树作为其根结点的左右子树,并将其两个子树的权值之和作为其根的权值。从集合中删除已经选中的二叉树,将新生成的树加入集合中参与下一轮选择
  • 重复上一步操作,直至集合中剩下最后一棵二叉树,这棵二叉树便是哈夫曼树
  • 哈夫曼树的构造过程
    在这里插入图片描述
  • 上述哈夫曼树的WPL值情况: W P L = 5 × 2 + 1 × 3 + 4 × 3 + 7 × 2 + 9 × 2 = 57 WPL= 5×2+1×3+4×3+7×2+9×2=57 WPL=5×2+1×3+4×3+7×2+9×2=57

哈夫曼编码

  • 一般地,设需要编码的字符集为{a₁, a₂, a₃, …, aₙ},各个字符出现的频率为{w₁, w₂, …, wₙ}。规定左分支为0,右分支为1,则从根结点到叶子结点经过的分支所组成的0和1字符串便是对应字符的编码,这就是哈夫曼编码。
  • 示意图
    在这里插入图片描述

哈夫曼树的实现

class Node(object):
    def __init__(self, weight):
        # 结点的权值
        self.weight = weight
        self.left = None
        self.right = None
        # 是否新构造根结点,新构造的结点不进行WPL计算
        self.isNew = False

    def __gt__(self, other):
        """用于对结点之间的排序"""
        return self.weight > other.weight

class huffmanTree(object):
    def __init__(self, nodeList):
        self.WPL = 0
        self.root = self.createHuffmanTree(nodeList)

    def createHuffmanTree(self, nodeList):
        """
        创建哈夫曼树
        :param nodeList: 森林中的单个结点构成的二叉树
        :return:
        """
        # 如果当前森林中二叉树棵树大于1
        while len(nodeList) > 1:
            # 森林中的二叉树进行排序
            nodeList.sort()
            # 获取根结点最小的二叉树
            left = nodeList.__getitem__(0)
            # 获取根结点次小的二叉树
            right = nodeList.__getitem__(1)
            # 构造新结点
            newNode = Node(left.weight + right.weight)
            newNode.isNew = True
            # 将新结点的左孩子结点指针指向left结点
            newNode.left = left
            # 将新结点的右孩子结点指针指向right结点
            newNode.right = right
            # 从森林中删除已选择的二叉树
            nodeList.pop(0)
            nodeList.pop(0)
            # 将新构造的二叉树加入森林中
            nodeList.append(newNode)
        return nodeList.__getitem__(0)

    def calculate_WPL(self, node, level):
        """
        计算哈夫曼树的wpl
        :param node: 根结点
        :param level: 层数
        :return:
        """
        if node != None:
            if not node.isNew:
                self.WPL += node.weight * level
            self.calculate_WPL(node.left, level+1)
            self.calculate_WPL(node.right, level+1)


if __name__ == "__main__":
    print('PyCharm')
    nodeList = []
    nodeList.append(Node(1))
    nodeList.append(Node(7))
    nodeList.append(Node(4))
    nodeList.append(Node(5))
    nodeList.append(Node(9))
    hufftree = huffmanTree(nodeList)
    hufftree.calculate_WPL(hufftree.root, 0)
    print("哈夫曼树的WPL:", hufftree.WPL)
  • 运行结果

在这里插入图片描述

相关文章:

  • 【Qt】常用控件【按钮类】
  • EfficientNet 改进:添加CAA上下文锚定注意模块(2024改进方法)
  • Xsens MTI:在海上为风力发电场选择最佳位置
  • 使用Apache POI(Java)创建docx文档和表格
  • Baklib三步构建企业内容中台
  • 尚硅谷Java第 4、5 章IDEA,数组
  • 今日行情明日机会——20250411
  • 深入解析AI Agent核心能力:经验学习、工具调用与动态规划
  • 【含文档+PPT+源码】基于微信小程序的高校特色服装租赁系统
  • 第9课:多智能体系统行业落地案例
  • Java I/O 流体系详解与记忆方法
  • JAVA基础 - 高效管理线程隔离数据结构ThreadLocalMap
  • AI避坑:AI生成的文件格式不一定对
  • BERT - Bert模型框架复现
  • 4.11时钟延迟
  • linux sar 系统运行状态统计
  • HarmonyOS-ArkUIV2装饰器-@Param:组件外部输入
  • Spark-core编程总结
  • 接听电话,手机靠近耳朵后拿开,挂断电话,设备自动锁屏
  • 漏洞扫描系统docker版本更新(2025.4.10)
  • 网站制作如皋/自己怎么制作网站
  • 设计与网站建设案例/网站站点查询
  • wordpress 多用户样式/网站seo教材
  • 宝石网站建设/国外域名购买
  • 巴中建设厅网站电话/企业查询平台
  • 鹤山市城乡住房建设部网站/日本比分算1:1