判断一棵树是否是另一棵树的子树(Java实现)

本文介绍了一种算法,用于判断一棵树是否为另一棵树的子树。通过递归比较节点,首先确保两棵树相等,再检查小树是否为大树的子节点或子孙节点组成的部分。

    前面一篇文章介绍了如何判断两棵树相等,思路就是遍历每个节点,然后判断是否均相等,需要用递归来实现。如果需要判断一棵树是另一棵树的子树,该怎么办呢?我们需要借助前面的思路,需要先判断两棵树相等,这里就是判断一棵树是另一棵树的一部分,也就是说如果是子树,那么这棵小树肯定是这棵大树某一个节点的子节点以及子孙节点组成的一部分。可以用到前面判断相等的方法。假定我们有两棵树的根节点,分别为t1,t2,如果我们判断t1.left和t2是相等的,或者是t1.right和t2是相等的,那么可以判断t2就是t1的子树。

    按照上面的思路,我们可以写出这样的程序。

package com.xxx.algorithm.wh;
public class Tree {
	public static class TreeNode{
		int data;
		public TreeNode(int data) {
			this.data = data;
			this.left = null;
			this.right = null;
		}
		TreeNode left;
		TreeNode right;
	}
	
	public static boolean equals(TreeNode t1,TreeNode t2){
		if(t1==null&&t2==null)
			return true;
		if(t1==null||t2==null)
			return false;
		return t1.data==t2.data && equals(t1.left, t2.left) && equals(t1.right, t2.right);
	}
	
	public static boolean subTree(TreeNode t1,TreeNode t2){
		if(t1==null)return false;
		if(equals(t1, t2))return true;
		return subTree(t1.left, t2) || subTree(t1.right, t2);
	}
	
	public static void main(String[] args) {
		//      a            b
		//------------------------
		//      10
		//     /  \
		//    9    8          9
		//   / \             / \
		//  7   6           7   6
		TreeNode a1 = new TreeNode(10);
		TreeNode a2 = new TreeNode(9);
		TreeNode a3 = new TreeNode(8);
		TreeNode a4 = new TreeNode(7);
		TreeNode a5 = new TreeNode(6);
		a1.left = a2;
		a1.right = a3;
		a2.left = a4;
		a2.right = a5;
		
		TreeNode b1 = new TreeNode(9);
		TreeNode b2 = new TreeNode(7);
		TreeNode b3 = new TreeNode(6);
		b1.left = b2;
		b1.right = b3;
		
		System.out.println("subTree(a,b)="+subTree(a1, b1));
		
	}
	
}

    运行程序,打印信息如下:

subTree(a,b)=true

    这里我们直接通过节点之间的关系构建了两棵树,分别是a,b,b是a的根节点的左子树,这里通过程序代码判断,是正确的,如果我们修改节点,那么判断就会返回假:

### 关于二叉树是否为一棵树子树的算法实现 判断一棵二叉树是否是一棵二叉树子树一个经典的递归问题。该问题的核心在于通过递归比较两棵的部分结构来验证它们的关系。 #### 方法概述 为了完成这一任务,通常会设计两个辅助函数: 1. **`isSameTree`**: 用于判断两棵是否完全相同。 2. **`isSubtree`**: 用于遍历主中的每一个节点,并将其作为潜在的根节点与目标子树进行匹配。 以下是具体的实现方式: --- #### C语言实现 ```c /** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ bool isSameTree(struct TreeNode* p, struct TreeNode* q) { if (p == NULL && q == NULL) return true; // 若两者都为空,则相同 if (p == NULL || q == NULL) return false; // 若其中一个为空而一个不为空,则不同 if (p->val != q->val) return false; // 值不同的情况返回false return isSameTree(p->left, q->left) && isSameTree(p->right, q->right); // 继续递归检查左右子树 } bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){ if (root == NULL) return false; // 主为空则不可能存在子树关系 if (isSameTree(root, subRoot)) return true; // 当前节点满足条件时直接返回true return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); // 向下递归寻找可能的匹配位置 } ``` 此代码实现了基本逻辑:先利用 `isSameTree` 函数逐层对比两棵的对应部分,再借助 `isSubtree` 遍历整棵以找到合适的起始点[^1]。 --- #### Java实现 ```java public class Solution { public boolean isSubtree(TreeNode s, TreeNode t) { if (s == null) return false; // 如果主已经遍历完毕仍未发现匹配项,则返回false if (isSame(s, t)) return true; // 发现有相同的子树即刻返回true return isSubtree(s.left, t) || isSubtree(s.right, t); // 对左右分支分别尝试匹配 } private boolean isSame(TreeNode s, TreeNode t) { if (s == null && t == null) return true; // 二者均无后续节点视为一致 if (s == null || t == null) return false; // 单侧有剩余节点说明无法构成子树 if (s.val != t.val) return false; // 节点值不符立即退出 return isSame(s.left, t.left) && isSame(s.right, t.right); // 进一步深入检测左右孩子结点的一致性 } } ``` 这段Java版本同样遵循了双层次递归的设计思路,在效率和可读性之间取得了平衡[^3]。 --- #### 时间复杂度分析 对于大小分别为 \(m\) 和 \(n\) 的两棵来说,最坏情况下需要对每一对组合执行一次完整的形结构比对操作,因此总体时间开销大致可以估计为 O(m \times n)[^2]。 尽管如此,实际运行过程中由于提前终止机制的存在(一旦确认某处不符合即可跳过其余无关计算),平均表现往往优于理论上限。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值