您的位置:首页 > 编程语言 > Java开发

判断一棵二叉树是否为另一棵二叉树的子结构(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;
}实例:
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结束。(如果太纠结递归那个过程很容易头晕脑胀的,所以还是简单点思考吧!)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 二叉树 递归