判断一棵二叉树是否为另一棵二叉树的子结构(JAVA版本)
2017-02-27 20:09
489 查看
分析:判断root1是否为root2的子树?首先,必须先找到树1中与树2的根节点相同的节点,然后判断从该节点开始root1中是否root2的结构;若有,则返回true,若没有,则返回false?答案是No! 因为二叉树root1中可能含有值相同的节点,所以,如果没有找到,就需要继续遍历root1.
Way: 先设计一个函数,isSame(root1,root2)判断给定相同根节点的两子树是否一样?再设计一个函数,递归遍历二叉树root1各个节点,当找到相同节点时,就调用isSame()方法判断是否具有相同的结构,若没有,则继续遍历,若有,递归返回。
核心实现代码块:
public static boolean isSame(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;
if(root1==null)
return false;//此时root2不为空,而root1却为空了,所以root2不是一的子结构
if(!root1.data.equals(root2.data))
return false;
return isSame(root1.leftChildren,root2.leftChildren)&&isSame(root1.rightChildren,root2.rightChildren);
}递归遍历:
//判断是否子树结构
public static boolean isSubTree(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;//如果root2我空节点,则是root1的子树
if(root1!=null){
if(root1.data.equals(root2.data) && isSame(root1,root2)){
//相等成立,表示在树1中找到了与树2根节点值相同的节点
//****root1中可能有多个节点与root2根相等,仅当是子结构才返回,若不是则继续遍历
return true;
}else{
//注意:此处不能分开写,递归理解:只要左子树或右子树中有一个包含子树即说明是root2是root1的子树
//若分开写,则左子树若判断除了是子树,在当前栈中返回了一个true,由于递归栈深度大,无法传递回来
return isSubTree(root1.leftChildren,root2) || isSubTree(root1.rightChildren,root2);
}
}
return false;
}实例:
(包含树的节点定义、前序创建、中序遍历)
class TreeNode<T> {
T data;
TreeNode<T> leftChildren;
TreeNode<T> rightChildren;
public TreeNode(T data){
this.data=data;
this.leftChildren=null;
this.rightChildren=null;
}
}
public class Mao {
public static void main(String[] args) {
//创建2颗二叉树
String str1="889##24##7##7##";
String str2="89##2##";
StringBuilder sb1=new StringBuilder(str1);
StringBuilder sb2=new StringBuilder(str2);
TreeNode<Character> root1=recurseCreateTree(sb1);
TreeNode<Character> root2=recurseCreateTree(sb2);
System.out.print("inOrder Tree1: ");
inOrder(root1);
System.out.print("\ninOrder Tree2: ");
inOrder(root2);
//判断
// root1=root2=null; // true
// root1=null; //false
// root2=null; //false
// root2.leftChildren.data='3'; //false
System.out.println("\n Tree2 is subTree of Tree1? "+isSubTree_better(root1,root2));
}
//判断是否子树结构
public static boolean isSubTree(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;//如果root2我空节点,则是root1的子树
if(root1!=null){
if(root1.data.equals(root2.data) && isSame(root1,root2)){
//相等成立,表示在树1中找到了与树2根节点值相同的节点
//****root1中可能有多个节点与root2根相等,仅当是子结构才返回,若不是则继续遍历
return true;
}else{
//注意:此处不能分开写,递归理解:只要左子树或右子树中有一个包含子树即说明是root2是root1的子树
//若分开写,则左子树若判断除了是子树,在当前栈中返回了一个true,由于递归栈深度大,无法传递回来
return isSubTree(root1.leftChildren,root2) || isSubTree(root1.rightChildren,root2);
}
}
return false;
}
//上述方法更好的可以写为:(尤其是在普通树结构中)
public static boolean isSubTree_better(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;
boolean flag=false;
if(root1!=null){
if(root1.data.equals(root2.data)){
flag=isSame(root1,root2);
}
if(!flag)
flag=isSubTree_better(root1.leftChildren,root2);
if(!flag)
flag=isSubTree_better(root1.rightChildren,root2);
}
return flag;
}
//比较两棵树是否一样
public static boolean isSame(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;
if(root1==null)
return false;//此时root2不为空,而root1却为空了,所以root2不是一的子结构
if(!root1.data.equals(root2.data))
return false;
return isSame(root1.leftChildren,root2.leftChildren)&&isSame(root1.rightChildren,root2.rightChildren);
}
//递归创建二叉树
public static TreeNode<Character> recurseCreateTree(StringBuilder str){
TreeNode<Character> node=null;
char data=str.toString().charAt(0);
str.delete(0,1);
if('#'!=data){
node=new TreeNode<Character>(data);
node.leftChildren=recurseCreateTree(str);
node.rightChildren=recurseCreateTree(str);
}
return node;
}
//二叉树的前序遍历
public static void inOrder(TreeNode<Character> root){
if(root!=null){
inOrder(root.leftChildren);
System.out.print(root.data+" ");
inOrder(root.rightChildren);
}
}
}输出结果为:
inOrder Tree1: 9 8 4 2 7 8 7
inOrder Tree2: 9 8 2
Tree2 is subTree of Tree1? true总结:本题重点在对二叉树的操作上,需要深入的理解递归的使用,以自己的见解(很浅):不需要深入考虑复杂的递归调用内部,而是单纯的将原问题划分子问题,如上述方法,出去对节点的null判断,实际就是在root1中找到与root2相等的节点,判断是否是子结构;如果不是,再看root1的左子树是否包含root2结构,再没有,就看右子树是否包含root2结构;最后加上个递归结束条件,root1传入的值为null结束。(如果太纠结递归那个过程很容易头晕脑胀的,所以还是简单点思考吧!)
Way: 先设计一个函数,isSame(root1,root2)判断给定相同根节点的两子树是否一样?再设计一个函数,递归遍历二叉树root1各个节点,当找到相同节点时,就调用isSame()方法判断是否具有相同的结构,若没有,则继续遍历,若有,递归返回。
核心实现代码块:
public static boolean isSame(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;
if(root1==null)
return false;//此时root2不为空,而root1却为空了,所以root2不是一的子结构
if(!root1.data.equals(root2.data))
return false;
return isSame(root1.leftChildren,root2.leftChildren)&&isSame(root1.rightChildren,root2.rightChildren);
}递归遍历:
//判断是否子树结构
public static boolean isSubTree(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;//如果root2我空节点,则是root1的子树
if(root1!=null){
if(root1.data.equals(root2.data) && isSame(root1,root2)){
//相等成立,表示在树1中找到了与树2根节点值相同的节点
//****root1中可能有多个节点与root2根相等,仅当是子结构才返回,若不是则继续遍历
return true;
}else{
//注意:此处不能分开写,递归理解:只要左子树或右子树中有一个包含子树即说明是root2是root1的子树
//若分开写,则左子树若判断除了是子树,在当前栈中返回了一个true,由于递归栈深度大,无法传递回来
return isSubTree(root1.leftChildren,root2) || isSubTree(root1.rightChildren,root2);
}
}
return false;
}实例:
root1: 8 / \ 8 7 / \ 9 2 / \ 4 7 root2: 8 / \ 8 7完整代码:
(包含树的节点定义、前序创建、中序遍历)
class TreeNode<T> {
T data;
TreeNode<T> leftChildren;
TreeNode<T> rightChildren;
public TreeNode(T data){
this.data=data;
this.leftChildren=null;
this.rightChildren=null;
}
}
public class Mao {
public static void main(String[] args) {
//创建2颗二叉树
String str1="889##24##7##7##";
String str2="89##2##";
StringBuilder sb1=new StringBuilder(str1);
StringBuilder sb2=new StringBuilder(str2);
TreeNode<Character> root1=recurseCreateTree(sb1);
TreeNode<Character> root2=recurseCreateTree(sb2);
System.out.print("inOrder Tree1: ");
inOrder(root1);
System.out.print("\ninOrder Tree2: ");
inOrder(root2);
//判断
// root1=root2=null; // true
// root1=null; //false
// root2=null; //false
// root2.leftChildren.data='3'; //false
System.out.println("\n Tree2 is subTree of Tree1? "+isSubTree_better(root1,root2));
}
//判断是否子树结构
public static boolean isSubTree(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;//如果root2我空节点,则是root1的子树
if(root1!=null){
if(root1.data.equals(root2.data) && isSame(root1,root2)){
//相等成立,表示在树1中找到了与树2根节点值相同的节点
//****root1中可能有多个节点与root2根相等,仅当是子结构才返回,若不是则继续遍历
return true;
}else{
//注意:此处不能分开写,递归理解:只要左子树或右子树中有一个包含子树即说明是root2是root1的子树
//若分开写,则左子树若判断除了是子树,在当前栈中返回了一个true,由于递归栈深度大,无法传递回来
return isSubTree(root1.leftChildren,root2) || isSubTree(root1.rightChildren,root2);
}
}
return false;
}
//上述方法更好的可以写为:(尤其是在普通树结构中)
public static boolean isSubTree_better(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;
boolean flag=false;
if(root1!=null){
if(root1.data.equals(root2.data)){
flag=isSame(root1,root2);
}
if(!flag)
flag=isSubTree_better(root1.leftChildren,root2);
if(!flag)
flag=isSubTree_better(root1.rightChildren,root2);
}
return flag;
}
//比较两棵树是否一样
public static boolean isSame(TreeNode<Character> root1,TreeNode<Character> root2){
if(root2==null)
return true;
if(root1==null)
return false;//此时root2不为空,而root1却为空了,所以root2不是一的子结构
if(!root1.data.equals(root2.data))
return false;
return isSame(root1.leftChildren,root2.leftChildren)&&isSame(root1.rightChildren,root2.rightChildren);
}
//递归创建二叉树
public static TreeNode<Character> recurseCreateTree(StringBuilder str){
TreeNode<Character> node=null;
char data=str.toString().charAt(0);
str.delete(0,1);
if('#'!=data){
node=new TreeNode<Character>(data);
node.leftChildren=recurseCreateTree(str);
node.rightChildren=recurseCreateTree(str);
}
return node;
}
//二叉树的前序遍历
public static void inOrder(TreeNode<Character> root){
if(root!=null){
inOrder(root.leftChildren);
System.out.print(root.data+" ");
inOrder(root.rightChildren);
}
}
}输出结果为:
inOrder Tree1: 9 8 4 2 7 8 7
inOrder Tree2: 9 8 2
Tree2 is subTree of Tree1? true总结:本题重点在对二叉树的操作上,需要深入的理解递归的使用,以自己的见解(很浅):不需要深入考虑复杂的递归调用内部,而是单纯的将原问题划分子问题,如上述方法,出去对节点的null判断,实际就是在root1中找到与root2相等的节点,判断是否是子结构;如果不是,再看root1的左子树是否包含root2结构,再没有,就看右子树是否包含root2结构;最后加上个递归结束条件,root1传入的值为null结束。(如果太纠结递归那个过程很容易头晕脑胀的,所以还是简单点思考吧!)
相关文章推荐
- 剑指Offer 面试题28:判断一棵二叉树是否镜对称 Java代码实现
- java、python语言判断一棵二叉树是否对称
- 判断一棵二叉树是否为对称的 java
- 判断二叉树是否包含另一棵二叉树或者树的子结构
- java 判断一棵二叉树是否为平衡二叉树
- 判断一棵二叉树是否为搜索二叉树、完全二叉树、平衡二叉树(java)
- Java代码 判断一棵二叉树是否为对称的
- 剑指offer 面试题18 判断二叉树B是否是A的子结构
- 如何判断一棵二叉树树是否为另一棵二叉树的子树
- [互联网面试笔试汇总C/C++-16] 判断一棵二叉树是否是平衡二叉树
- 输入一棵二叉树,判断该二叉树是否是平衡二叉树。
- 判断表达式括号是否匹配java和js版本
- 剑指offer解题报告(Java版)——二叉树的深度 判断二叉树是否平衡 38
- 判断一棵二叉树是否是二叉排序树
- Java代码 给出一个二叉树和一个数,判断该二叉树是否存在一个从根节点到叶节点的和与给出的数相同
- 判断一棵二叉树是否为AVL树
- 数据结构之如何判断一棵二叉树是否是平衡二叉树(AVL树)
- [互联网面试笔试汇总C/C++-14] 判断一棵二叉树是否是二叉搜索树-微策略
- 【BST】判断一棵二叉树是否是搜索二叉树
- 【二叉树】判断一棵二叉树是否是平衡二叉树