树的同构问题
一、问题引入
给定两棵树 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.解决步骤
- 输入处理
• 读取每棵树的节点数
• 为每棵树构建节点信息和子节点关系
• 确定每棵树的根节点(没有父节点的节点) - 同构判断
• 基本情况处理:
◦ 如果两个根节点都为空,返回True
◦ 如果一个为空另一个不为空,返回False
◦ 如果根节点存储的值不同,返回False
• 递归比较:
◦ 情况1:不交换左右子树进行比较
◦ 情况2:交换左右子树进行比较
◦ 只要有一种情况匹配就返回True - 结果输出
• 根据递归比较结果输出"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")
算法分析
- 时间复杂度:O(n²),在最坏情况下需要比较所有节点的组合
- 空间复杂度:O(n),用于存储树的结构和递归调用栈
四、个人总结
通过本次实验,我对树的同构问题有了更深入的理解。在解决问题的过程中,我学会了如何从实际问题出发,将抽象的树结构转化为具体的代码实现。实验初期,我一度困惑于如何判断两棵树是否同构,但通过仔细分析题目示例,我逐渐认识到关键在于递归地比较节点的值及其子树结构。
在实现过程中,我掌握了处理树形结构输入的有效方法,特别是如何通过标记父节点来准确找到树的根节点。这次实验让我深刻体会到递归思想在解决树结构问题中的强大作用,通过将大问题分解为相同性质的子问题,可以优雅地解决看似复杂的结构匹配问题。同时,我也认识到边界条件处理的重要性,比如空树情况的处理、单节点树的比较等细节都会直接影响程序的正确性。
在调试过程中,我通过打印中间结果验证了递归调用的正确性,这让我对递归的执行过程有了更直观的认识。此外,本次实验还让我意识到算法效率的重要性,虽然递归解法简洁易懂,但在处理大规模数据时可能面临性能问题。总的来说,这次实验不仅让我掌握了树同构问题的解决方法,更重要的是培养了我分析问题、设计算法的能力,这对今后学习更复杂的数据结构和算法打下了坚实基础。