二叉树求子树Java实现

在准备Amazon的面试,有一道题目是这样的。

已知两个树A,B,求B是否是A的子树。



其实题目并不难。不知道为什么我就把自己困在建树上了。我记得我上一次写二叉树也是把自己困在建树上了。其实遍历什么的都很清晰。我也不记得我两年前是怎么建树的了,这次重新写了一个。

不知道在哪里看的实例输入里面有0,从此0在我脑海里面根深蒂固。我的输入还蛮奇怪的。仔细想想其实还是不把0纳入考虑,因为会影响结果。不过懒得改了。。。建树建成我这样也是。。。

先看重点的好了,参考了网上现有的很多博客。我已经不记得当时看到的是哪个了。

思路很清晰:

	public boolean HasSubTree(Node root1, Node root2) {
		// TODO Auto-generated method stub
		boolean result = false;
		if(root1 != null && root2 != null)//排除特殊根不存在的特殊情况
		{
			if(root1.val == root2.val)//如果两个根一样,测试
			{
				result = DoesTree1HasTree2(root1,root2);
			}
		}
		if(result!=true)
		{
			result = DoesTree1HasTree2(root1.left,root2);
		}
		if(result!=true)
		{
			result = DoesTree1HasTree2(root1.right,root2);
		}
		
		return result;
	}

	private boolean DoesTree1HasTree2(Node root1, Node root2) {
		// TODO Auto-generated method stub
		boolean lflag = false;
		boolean rflag = false;
		
		if(root2 == null)
			return true;//测试到树B结尾了,搞定
		
		if(root1 == null)
			return false;//测到树A结尾了,没有办法继续,B一定不是A子树
		
		if(root1.val != root2.val)
		{
			return false;//最后不同
		}else
		{
			lflag = DoesTree1HasTree2(root1.left,root2.left);
			rflag = DoesTree1HasTree2(root1.right, root2.right);
			
			return lflag&&rflag;
		}
	}
主函数:

package Tree;

import Tree.BinaryTree.Node;

public class HasSubtree {
	/*
	 * 输入两棵树A和B,判断B是不是A的子树
	 */
	
	public static void main(String[] args){
		
		System.out.println("============================= Tree 1 ==========================================");
		/*
		 *         1
		 *      /     \
		 *     2       3
		 *   /  \     /  \
		 *  4    5   0    6
		 * / \  / \
		 * 0  0	7 0
		       /\
		      0 0
		 */
		int[] data01 = {1,2,4,0,0,5,7,0,0,0,3,0,6};
		BinaryTree bTree = new BinaryTree();		
		bTree.root = bTree.buildTree(bTree.root,data01);
		bTree.PreOrderTraverse(bTree.root);
		
		System.out.println("============================= Tree 2 ==========================================");
		int[] data02 = {2,4,0,0,5};
		BinaryTree bTree2 = new BinaryTree();		
		bTree2.root = bTree2.buildTree(bTree2.root,data02);		
		bTree2.PreOrderTraverse(bTree2.root);
		
		boolean flag = false;
		flag = bTree.HasSubTree(bTree.root,bTree2.root);
		System.out.println("=======================================\n"+flag);

		
	}



}

二叉树部分:

package Tree;

import java.util.Stack;

import Tree.BinaryTree.Node;

public class BinaryTree {

	Node root;
	Node parent = null;
	
	public static class Node{
		int val;
		Node left;
		Node right;
		
		public Node(int val)
		{
			this.left = null;
			this.right = null;
			this.val = val;
		}
	}
	
	public BinaryTree()
	{
		root = null;
	}

	public Node buildTree(Node root, int[] data) {
		// TODO Auto-generated method stub
		int i=0;
		Node nowNode= null;
		Node LastNode = null;
		if(root == null)
			{
				root = new Node(data[i]);
				nowNode = root;
				LastNode = root;
				i++;
			}		
		
		while(i < data.length)
		{
//			System.out.println("while:   i:"+i+" 要存入的是: "+data[i]+" 叶子节点是: "+nowNode.val);
			if(nowNode.val == 0)
			{
				
				if(LastNode.right == null)
				{
					Node node = new Node(data[i]);
					LastNode.right = node;
					nowNode = LastNode.right;
					i++;
					parent = null;
					nowNode = FindParentsNode(root,LastNode);
				}else
				{
//					System.out.println("Last: "+LastNode.val +"\tNow : "+nowNode.val);
					while(nowNode!=null)
					{
						parent = null;
						
						if(nowNode.right!=null)
						{
							LastNode = nowNode;
							parent = null;
							nowNode = FindParentsNode(root,LastNode);

						}else
						{
//							System.out.println("Out of Bounds:\t"+i);
							Node node = new Node(data[i]);
							LastNode = nowNode;
							nowNode.right = node;
							nowNode = nowNode.right;
							i++;
							break;

						}
					}
					
					
					
				}
			}else
			{
				if(nowNode.left == null)
				{
//					
						Node node = new Node(data[i]);
						nowNode.left = node;
						LastNode = nowNode;
						nowNode = nowNode.left;
//						System.out.println("i:"+i+"要存入的是: "+data[i]+" 叶子节点是: "+nowNode.val);
						i++;
					} 	
				else
				{
					Node node = new Node(data[i]);
					nowNode.right = node;
					LastNode = nowNode;
					nowNode =nowNode.right;
					i++;
				}
			}

			}
		return root;
		

		
	}

	private Node FindParentsNode(Node root2, Node node) {
		// TODO Auto-generated method stub
		Node p = root2;
		
		if(p != null)
		{
//			System.out.println(p.val);
			if(p.left!=null)
			if(p.left.val == node.val)
				parent = p;
			if(p.right!=null)
			if(p.right.val == node.val)
				parent = p;
				
			FindParentsNode(p.left,node);
			FindParentsNode(p.right,node);
		}else
			return parent;
		return parent;
	}
	
	void PreOrderTraverse(Node root) {
		// TODO Auto-generated method stub
		Node p = root;
		if(p != null)
		{
			System.out.println(p.val);
			PreOrderTraverse(p.left);
			PreOrderTraverse(p.right);
		}else
			return;
		
	}

	public boolean HasSubTree(Node root1, Node root2) {
		// TODO Auto-generated method stub
		boolean result = false;
		if(root1 != null && root2 != null)
		{
			if(root1.val == root2.val)
			{
				result = DoesTree1HasTree2(root1,root2);
			}
		}
		if(result!=true)
		{
			result = DoesTree1HasTree2(root1.left,root2);
		}
		if(result!=true)
		{
			result = DoesTree1HasTree2(root1.right,root2);
		}
		
		return result;
	}

	private boolean DoesTree1HasTree2(Node root1, Node root2) {
		// TODO Auto-generated method stub
		boolean lflag = false;
		boolean rflag = false;
		
		if(root2 == null)
			return true;//测试到树B结尾了,搞定
		
		if(root1 == null)
			return false;//测到树A结尾了,没有办法继续,B一定不是A子树
		
		if(root1.val != root2.val)
		{
			return false;//最后不同
		}else
		{
			lflag = DoesTree1HasTree2(root1.left,root2.left);
			rflag = DoesTree1HasTree2(root1.right, root2.right);
			
			return lflag&&rflag;
		}
	}
	
	
}




### Python 实现二叉树并查找子 #### 定义二叉树节点类 为了实现二叉树以及在其上执行操作,首先需要定义一个表示二叉树节点的类 `TreeNode`。此类包含三个属性:当前节点存储的值 (`value`)、指向左孩子的指针 (`left`) 以及指向右孩子的指针 (`right`)。 ```python class TreeNode: def __init__(self, value=0, left=None, right=None): self.value = value self.left = left self.right = right ``` #### 构建二叉树实例 通过上述定义好的 `TreeNode` 类型对象来创建具体的二叉树结构。可以通过设置各个节点之间的连接关系完成整棵的建立[^2]。 #### 子匹配函数设计 对于给定的一棵大 T 和一棵小 S ,要判断S 是否为T 的子,则可以从根结点开始比较两棵是否相同;如果不同则继续分别尝试用T 左/右分支作为新的大数再做同样的对比直到找到完全一致的部分为止或者遍历结束仍无果返回False 。这里给出一种基于递归的方法: ```python def is_subtree(large_tree_node, small_tree_node): if not large_tree_node and not small_tree_node: return True if not large_tree_node or not small_tree_node: return False # Check from root node of both trees. same_trees = are_identical(large_tree_node, small_tree_node) # If the above call returns false then check for subtree in left and right children of larger tree if same_trees: return True else: return (is_subtree(large_tree_node.left, small_tree_node) or is_subtree(large_tree_node.right, small_tree_node)) def are_identical(root1, root2): """Helper function to determine whether two binary trees rooted at given nodes are identical.""" if not root1 and not root2: return True if not root1 or not root2: return False return ((root1.value == root2.value) and are_identical(root1.left , root2.left ) and are_identical(root1.right, root2.right)) ``` 这段代码实现了两个主要功能:一是检测整个二叉树是否相等(`are_identical`);二是检查较小的那颗二叉树是不是较大一颗中的某个部分即所谓的“子”(`is_subtree`). 这里采用的是先序的方式来进行逐层深入地验证每一个可能成为候选者的节点及其后代们是否存在符合条件的情况[^4].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值