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

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

一、概念

带权路径长度最短的二叉树,即最优二叉树。

二、带权路径长度

在一颗树中,叶子结点带有数值,这个数值叫做权值,

权值与叶子结点到根节点层数的乘积=带权路径长度

三、树的带权路径长度

树中所有叶节点的带权路径长度之和

四、举例

在这里插入图片描述
树的带权路径长度计算:3x1+5x2=13

五、哈夫曼树画法举例举例理解

5.1步骤

(1) 先准备一组数字,以5,7,5,8, 9,2, 3为例
(2) 对这一组数字进行从小到大的规则排序,排序结果为2, 3, 5 ,5, 7, 8, 9
(3) 在2, 3, 5 ,5, 7, 8, 9这些数字中,选择两个最小的数字2,3
(4) 用类似树杈的“树枝”连接两个最小的数,在顶点处计算出这两个数字的和,比较剩下的数字和这个和的大小,再取出两个最小的数字进行排序。
排序结果如下:
在这里插入图片描述

5.2注意

1.如果两个数的和等于是下一步两个最小数其中一个,那么这个树直接往上生长。如上图的5,5,左边的5直接向上生长。如果两个数的和比较大,不是下一步两个最小数其中一个,那么就并列生长,例如我们的左边5,5的和为10,而10不等于接下来选出的两个数字5,7,所以要另外开一棵二叉树。

2.一个节点只能生成两个分支。

六、举例(代码实现)

要求:将2, 3, 5 ,5, 7, 8, 9画出来

6.1代码

#coding=utf-8
import pygraphviz as pgv
import cv2
import os
import tkinter as tk

Index = 0


#  二叉树
class BTree:
    lchild = None
    rchild = None
    data = 0
    index = 0

    def __init__(self, data, index):
        self.data = data
        self.index = index
        return

    def getchild(self, lc, rc):
        self.lchild = lc
        self.rchild = rc
        return


#  用来预处理哈夫曼树
def PreHuffTree(bt, dot):
    if (bt == None): return

    dot.add_node(bt.index, label=str(bt.data))

    PreHuffTree(bt.lchild, dot)
    PreHuffTree(bt.rchild, dot)

    if (bt.lchild != None):
        dot.add_edge(bt.index, bt.lchild.index, )
    if (bt.rchild != None):
        dot.add_edge(bt.index, bt.rchild.index)
    return


#  str转换为int类型
def GetSomeValue(hl):
    global Index
    ht = []
    for x in range(len(hl)):
        ht.append(BTree(int(hl[x]), Index))
        Index += 1
    return ht


#  对数据进行连接形成二叉树
def TransFromHuffTree(hl):
    global Index
    if (len(hl) == 0):
        print("未输入数值")
        return
    while len(hl) > 1:
        hl = sorted(hl, key=lambda x: x.data)
        hf = BTree(hl[0].data + hl[1].data, Index)
        Index += 1
        hf.getchild(hl[0], hl[1])
        hl.pop(0)
        hl.pop(0)
        hl.append(hf)
    return hl[0]


if __name__ == "__main__":
    HuffTreelist = []
    root = tk.Tk()
    values = ""
    HuffTreelist = []

    tk.Label(root, text='请输入一系列数值,以空格间隔 :').grid(row=0, column=0)  # 对Label内容进行 表格式 布局
    v1 = tk.StringVar()
    e1 = tk.Entry(root, textvariable=v1)
    e1.grid(row=0, column=1, padx=10, pady=5)


    def GetValue():
        global values, HuffTreelist, v1
        values = v1.get()
        values = values.split()
        for x in range(len(values)):
            if not values[x].isnumeric():
                v1.set("输入错误:包含非数字字符")
                break
        return


    tk.Button(root, text='确认', width=10, command=GetValue).grid(row=1, column=0, sticky=tk.W, padx=10, pady=5)
    tk.Button(root, text='退出', width=10, command=root.quit).grid(row=1, column=1, sticky=tk.E, padx=10, pady=5)

    tk.mainloop()
    root.destroy()

    HuffTreelist = GetSomeValue(values)
    HuffTree = TransFromHuffTree(HuffTreelist)

    dot = pgv.AGraph(directed=False, strict=True)
    PreHuffTree(HuffTree, dot)

    dot.layout('dot')
    dot.draw('d:/b.png')
    pic = cv2.imread('d:/b.png')
    cv2.imshow("hufftree", pic)
    cv2.waitKey(0)

    os.remove('d:/b.png')






代码参考:https://blog.csdn.net/qq_41654225/article/details/101302587
运行结果:
在这里插入图片描述
注意
要以空格分隔,否则
在这里插入图片描述
在这里插入图片描述

注意
只能输入数字,否则
在这里插入图片描述
在这里插入图片描述

正确输入2 3 5 5 7 8 9 ,点击确认,再点击退出
在这里插入图片描述

6.2运行结果

在这里插入图片描述

注意

如果pycharm没有进行管理员运行,会出现以下报错:

Traceback (most recent call last):
  File "F:/自动化测试工具/Pycharm的项目/model/teacher.py", line 107, in <module>
    dot.draw('d:/b.png')
  File "F:\Python\lib\site-packages\pygraphviz\agraph.py", line 1518, in draw
    fh = self._get_fh(path, 'w+b')
  File "F:\Python\lib\site-packages\pygraphviz\agraph.py", line 1547, in _get_fh
    fh = open(path, mode=mode)
PermissionError: [Errno 13] Permission denied: 'd:/b.png'

在这里插入图片描述

希望对大家有帮助!

<think>嗯,用户想用EasyX库绘制哈夫曼。首先,我得回忆一下哈夫曼的构建过程和EasyX的基本用法。哈夫曼通常是通过最小堆来构建的,对吧?然后每次取出两个最小的节点,合并成一个新节点,再放回堆里,直到堆里只剩一个根节点。这部分用户可能已经了解,但需要结合图形化显示。 接下来,EasyX库是用于图形编程的,所以需要初始化窗口、绘制节点和连线。用户可能需要先构建哈夫曼的结构,然后在屏幕上递归地出每个节点,处理坐标的位置,确保的结构清晰。比如,根节点在顶部,左右子节点逐渐向下展开,可能需要计算每个节点的位置,避免重叠。 然后,用户提供的引用中提到了一些代码示例,比如使用init_display_window和draw_huffman_tree函数。这可能涉及到设置节点的坐标,使用EasyX的绘图函数如circle、outtextxy、line等。需要注意的是,递归绘制子时,水平间距可能需要根据层级调整,比如越深的层级间距越小,这样看起来更平衡。 另外,引用[3]提到需要安装EasyX图形库,但用户可能已经安装了,不过还是要确认。代码中可能需要包含相应的头文件,比如graphics.h。同时,处理节点的坐标计算是关键,可能需要根据的深度和宽度动态调整位置,保证每个节点的位置正确,并且连线准确连接到子节点。 用户可能遇到的问题包括坐标计算不正确导致节点重叠,或者递归绘制时层次处理错误。需要确保每个节点的位置计算正确,比如使用左右子的偏移量,逐层递减水平间距。同时,要注意EasyX的坐标系,原点是左上角,y轴向下增加,所以在计算垂直位置时要考虑这一点。 还有,颜色和文本的显示也需要处理,比如节点用不同颜色区分,字符和权值显示在节点旁边或内部。可能需要设置文本的对齐方式,确保文字居中显示在节点内。此外,处理窗口的关闭和消息循环,防止程序绘制完成后立即退出。 测试部分,用户可能需要一个示例数据来验证,比如引用[2]中的频率数组和字符数组。通过构建哈夫曼,然后调用绘制函数,检查图形是否正确显示。如果出现问题,可能需要调试坐标计算或递归绘制的逻辑。 总结一下,步骤应该是:构建哈夫曼结构,设计节点的坐标计算方式,使用EasyX函数绘制节点和连线,递归处理子,调整布局美观。同时,处理窗口初始化和关闭,确保程序运行流畅。</think>### 使用EasyX库绘制哈夫曼实现步骤 #### 1. **环境准备** - 安装EasyX图形库(从官网下载对应Visual Studio版本的安装包) - 创建C/C++项目并包含头文件: ```c #include <graphics.h> #include <conio.h> ``` #### 2. **数据结构设计** 定义哈夫曼节点结构: ```c struct HTNode { char data; // 字符 int weight; // 权值 HTNode* lchild; // 左子节点 HTNode* rchild; // 右子节点 int x, y; // 节点绘制坐标 }; typedef HTNode* HuffmanTree; ``` #### 3. **核心绘制逻辑** 递归绘制形结构的核心函数: ```c void drawTree(HuffmanTree root, int x, int y, int level, int offset) { if (root == nullptr) return; // 设置节点位置 root->x = x; root->y = y; // 绘制当前节点 setfillcolor(0x66CCFF); // 节点颜色 fillcircle(x, y, 20); // 绘制圆形节点 char text[32]; sprintf(text, "%c:%d", root->data, root->weight); outtextxy(x-15, y-8, text); // 显示字符和权值 // 递归绘制子节点(调整偏移量) if (root->lchild) { int childX = x - offset/(level*0.5); // 左子X坐标递减 line(x, y+20, childX, y+80-20); // 绘制连接线 drawTree(root->lchild, childX, y+80, level+1, offset/2); } if (root->rchild) { int childX = x + offset/(level*0.5); // 右子X坐标递增 line(x, y+20, childX, y+80-20); drawTree(root->rchild, childX, y+80, level+1, offset/2); } } ``` #### 4. **窗口初始化与调用** ```c void visualizeHuffman(HuffmanTree root) { initgraph(1024, 768); // 创建图形窗口 setbkcolor(0xF0F0F0); // 设置背景色 cleardevice(); drawTree(root, 512, 50, 1, 300); // 从顶部中心开始绘制 getch(); // 等待按键 closegraph(); // 关闭图形窗口 } ``` #### 5. **完整调用示例** ```c // 构建哈夫曼后调用 HuffmanTree tree = buildHuffmanTree(); // 假设已实现构建函数 visualizeHuffman(tree); ``` #### 关键优化点 1. **动态偏移调整**:通过`offset/(level*0.5)`实现层级越深子间距越小 2. **自动居中布局**:初始坐标`(512,50)`基于1024宽度窗口居中 3. **信息复合显示**:节点内同时显示字符和权值(如`A:15`) 4. **颜色标识**:采用渐变色区分不同层级节点[^3]
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值