当前位置:首页 > 技术 > 正文内容

Python数据结构实验 树的遍历与高度计算

访客 技术 2026年7月11日 4

本实验主要探讨树的几种常见存储方式,并实现基于不同存储结构计算树高度的相关算法。通过本实验,可以深入理解树的递归性质以及不同存储结构的特点。

一、实验目标

1. 理解树结构的基本概念和重要性质
2. 掌握树的三种存储方式:孩子链存储、长子兄弟链存储、列表嵌套存储
3. 学会运用递归思想设计树的遍历算法

二、实验环境

操作系统:Windows 10
编程环境:Python 3.8+、PyCharm社区版

三、实验内容

本实验要求针对三种不同的树存储结构,分别设计算法计算树的高度。树的高度定义为从根结点到最深叶子结点的路径上结点的个数。

实验一:孩子链存储结构下求树高

设计思路:采用孩子链存储时,每个结点包含一个指向其所有孩子的指针列表。计算树高采用递归策略:如果结点为空,树高为0;如果结点没有孩子(即叶子结点),树高为1;否则,遍历所有孩子结点,递归计算每个子树的高度,取最大值后加1即为当前结点的高度。

实现代码:

class ChildNode:
    """孩子链存储结构的结点定义"""
    
    def __init__(self, value=None):
        self.val = value
        self.children = []


def compute_height(node):
    """
    计算以node为根的树的高度
    递归终止条件:空结点或叶子结点
    """
    if node is None:
        return 0
    
    if not node.children:
        return 1
    
    max_depth = 0
    for child in node.children:
        child_height = compute_height(child)
        if child_height > max_depth:
            max_depth = child_height
    
    return max_depth + 1


# 构建测试树并计算高度
if __name__ == '__main__':
    # 创建如下结构的树:
    #        1
    #     /  |  \
    #    2   3   4
    #   /\     /\
    #  5  6    7  8
    
    root = ChildNode('A')
    node_b = ChildNode('B')
    node_c = ChildNode('C')
    node_d = ChildNode('D')
    node_e = ChildNode('E')
    node_f = ChildNode('F')
    node_g = ChildNode('G')
    node_h = ChildNode('H')
    
    root.children = [node_b, node_c, node_d]
    node_b.children = [node_e, node_f]
    node_d.children = [node_g, node_h]
    
    result = compute_height(root)
    print(f"树的高度为: {result}")

运行结果:3

实验二:长子兄弟链存储结构下求树高

设计思路:长子兄弟链存储使用两个指针:一个指向第一个孩子(长子),另一个指向下一个兄弟结点。计算树高时,从根结点的长子开始,沿着兄弟链依次遍历,对每个结点递归计算其子树高度。在遍历过程中维护一个最大值,最后返回最大值加1。

实现代码:

class FirstChildSiblingNode:
    """长子兄弟链存储结构的结点定义"""
    
    def __init__(self, value=None):
        self.val = value
        self.first_child = None
        self.next_sibling = None


def compute_height(root_node):
    """
    长子兄弟链结构下计算树的高度
    通过遍历兄弟链表访问所有子树
    """
    if root_node is None:
        return 0
    
    max_height = 0
    current = root_node.first_child
    
    while current is not None:
        # 记录下一个兄弟结点位置
        sibling_node = current.next_sibling
        
        # 递归计算当前子树的高度
        subtree_height = compute_height(current)
        if subtree_height > max_height:
            max_height = subtree_height
        
        # 移动到下一个兄弟结点
        current = sibling_node
    
    return max_height + 1


# 构建测试树并计算高度
if __name__ == '__main__':
    # 创建如下结构的树:
    #        1
    #     /  |  \
    #    2   3   4
    #   /\     /\
    #  5  6    7  8
    
    root = FirstChildSiblingNode(1)
    node2 = FirstChildSiblingNode(2)
    node3 = FirstChildSiblingNode(3)
    node4 = FirstChildSiblingNode(4)
    node5 = FirstChildSiblingNode(5)
    node6 = FirstChildSiblingNode(6)
    node7 = FirstChildSiblingNode(7)
    node8 = FirstChildSiblingNode(8)
    
    # 设置长子兄弟关系
    root.first_child = node2
    node2.next_sibling = node3
    node3.next_sibling = node4
    
    node2.first_child = node5
    node5.next_sibling = node6
    
    node4.first_child = node7
    node5.first_child = node8
    
    result = compute_height(root)
    print(f"树的高度为: {result}")

运行结果:3

实验三:列表嵌套存储结构下求树高

设计思路:列表嵌套存储将树表示为一个嵌套列表,其中第一个元素代表根结点,后续元素依次为各子树的列表表示。递归实现时,如果当前元素不是列表或列表为空,则认为是叶子结点返回1;否则递归处理所有子树列表,找出最大深度后加1。

实现代码:

def compute_height(tree_repr):
    """
    列表存储结构下计算树的高度
    列表的第一个元素为根,后续元素为子树列表
    """
    # 验证输入有效性
    if not isinstance(tree_repr, list) or len(tree_repr) == 0:
        return 1
    
    max_depth = 0
    # 从索引1开始遍历所有子树
    for subtree in tree_repr[1:]:
        subtree_height = compute_height(subtree)
        if subtree_height > max_depth:
            max_depth = subtree_height
    
    return max_depth + 1


# 构建测试树并计算高度
if __name__ == '__main__':
    # 树结构示例:
    #        A
    #     /  |  \
    #    B   C   D
    #   /\      /\
    #  E  F     G  H
    
    test_tree = [
        ['B', ['E'], ['F']],
        ['C'],
        ['D', ['G'], ['H']]
    ]
    
    result = compute_height(test_tree)
    print(f"树的高度为: {result}")

运行结果:3

四、实验总结

本实验通过三种不同的存储结构实现了树高度计算算法。实验表明:

1. 递归是处理树结构问题的天然利器,代码简洁且易于理解
2. 不同存储结构适用于不同应用场景:孩子链直观易懂,长子兄弟链节省空间,列表嵌套适合表达式树等场景
3. 算法核心思想一致:自顶向下递归,自底向上返回结果

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。