树的同构问题--Python

树的同构问题

一、问题引入

给定两棵树 T1和 T2。如果 T1可以通过若干次左右孩子互换就变成 T2,则我们称两棵树是"同构"的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。

现给定两棵树,请你判断它们是否是同构的。

输入格式:

输入给出2棵二叉树的信息。对于每棵树,首先在一行中给出一个非负整数 n (≤10),即该树的结点数(此时假设结点从 0 到 n−1 编号);随后 n 行,第 i 行对应编号第 i 个结点,给出该结点中存储的 1 个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出 "-"。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:

如果两棵树是同构的,输出"Yes",否则输出"No"。

输入样例:

8

A 1 2

B 3 4

C 5 -

D - -

E 6 -

G 7 -

F - -

H - -

8

G - 4

B 7 6

F - -

A 5 1

H - -

C 0 -

D - -

E 2 -

输出样例:

Yes

二、问题分析

1.思维导图

2.解决步骤

  1. 输入处理
    • 读取每棵树的节点数
    • 为每棵树构建节点信息和子节点关系
    • 确定每棵树的根节点(没有父节点的节点)
  2. 同构判断
    • 基本情况处理:
    ◦ 如果两个根节点都为空,返回True
    ◦ 如果一个为空另一个不为空,返回False
    ◦ 如果根节点存储的值不同,返回False
    • 递归比较:
    ◦ 情况1:不交换左右子树进行比较
    ◦ 情况2:交换左右子树进行比较
    ◦ 只要有一种情况匹配就返回True
  3. 结果输出
    • 根据递归比较结果输出"Yes"或"No"

三、代码实现

代码

python 复制代码
def read_tree(n):
    nodes = {}
    children = {}
    has_parent = [False] * n
    for i in range(n):
        data, left, right = input().split()
        nodes[i] = data
        left = int(left) if left != '-' else None
        right = int(right) if right != '-' else None
        children[i] = (left, right)
        if left is not None:
            has_parent[left] = True
        if right is not None:
            has_parent[right] = True
    root = None
    for i in range(n):
        if not has_parent[i]:
            root = i
            break
    return nodes, children, root

def is_isomorphic(root1, root2, nodes1, nodes2, children1, children2):
    if root1 is None and root2 is None:
        return True
    if root1 is None or root2 is None:
        return False
    if nodes1[root1] != nodes2[root2]:
        return False
    # Compare without swapping
    left1, right1 = children1[root1]
    left2, right2 = children2[root2]
    case1 = is_isomorphic(left1, left2, nodes1, nodes2, children1, children2) and \
            is_isomorphic(right1, right2, nodes1, nodes2, children1, children2)
    # Compare with swapping
    case2 = is_isomorphic(left1, right2, nodes1, nodes2, children1, children2) and \
            is_isomorphic(right1, left2, nodes1, nodes2, children1, children2)
    return case1 or case2

n1 = int(input())
nodes1, children1, root1 = read_tree(n1)
n2 = int(input())
nodes2, children2, root2 = read_tree(n2)

if is_isomorphic(root1, root2, nodes1, nodes2, children1, children2):
    print("Yes")
else:
    print("No")

算法分析

  1. 时间复杂度:O(n²),在最坏情况下需要比较所有节点的组合
  2. 空间复杂度:O(n),用于存储树的结构和递归调用栈

四、个人总结

通过本次实验,我对树的同构问题有了更深入的理解。在解决问题的过程中,我学会了如何从实际问题出发,将抽象的树结构转化为具体的代码实现。实验初期,我一度困惑于如何判断两棵树是否同构,但通过仔细分析题目示例,我逐渐认识到关键在于递归地比较节点的值及其子树结构。

在实现过程中,我掌握了处理树形结构输入的有效方法,特别是如何通过标记父节点来准确找到树的根节点。这次实验让我深刻体会到递归思想在解决树结构问题中的强大作用,通过将大问题分解为相同性质的子问题,可以优雅地解决看似复杂的结构匹配问题。同时,我也认识到边界条件处理的重要性,比如空树情况的处理、单节点树的比较等细节都会直接影响程序的正确性。

在调试过程中,我通过打印中间结果验证了递归调用的正确性,这让我对递归的执行过程有了更直观的认识。此外,本次实验还让我意识到算法效率的重要性,虽然递归解法简洁易懂,但在处理大规模数据时可能面临性能问题。总的来说,这次实验不仅让我掌握了树同构问题的解决方法,更重要的是培养了我分析问题、设计算法的能力,这对今后学习更复杂的数据结构和算法打下了坚实基础。

相关推荐
鹿角片ljp3 小时前
LeetCode 46. 全排列|吃透回溯
算法·leetcode·职场和发展
鼎艺创新科技3 小时前
不依赖 UE/Unity:我们如何从零搭建一套国产三维 GIS 渲染引擎
人工智能·算法·unity·游戏引擎·三维电子沙盘
剩下了什么3 小时前
float32 与 float64 精度陷阱:如何在 Go 中避免错误使用
开发语言·后端·golang
指尖时光.4 小时前
Three.js 超全入门综合案例
开发语言·javascript·ecmascript
暴力求解4 小时前
Linux网络---传输层协议TCP(二)
linux·服务器·开发语言·网络·tcp/ip
程序员三藏4 小时前
Python+requests实现接口自动化测试
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
吴声子夜歌4 小时前
Java面试题——基础(一)
java·开发语言
小庞在加油5 小时前
WinDbg实战:QT/跨平台项目死锁与无响应问题排查指南
开发语言·qt·windbg·工具
Vae_Mars5 小时前
C#中的delegate委托
开发语言·c#
一直走下去-明5 小时前
简单的http抓包解包完整代码
开发语言·python