剑指Offer(Java版):树的子结构

本文介绍了一种算法,用于判断一棵二叉树是否为另一棵二叉树的子结构。通过递归方法,在树A中查找与树B根节点值相同的节点,并验证其子树结构是否一致。

二叉树的结构定义为:

 

[java] view plain copy

 

  1. package utils;  
  2.   
  3. public class BinaryTreeNode {  
  4.     public int value;  
  5.     public BinaryTreeNode leftNode;  
  6.     public BinaryTreeNode rightNode;  
  7.       
  8.     public BinaryTreeNode(){  
  9.           
  10.     }  
  11.     public BinaryTreeNode(int value){  
  12.         this.value = value ;  
  13.         this.leftNode = null;  
  14.         this.rightNode = null;  
  15.     }  
  16.       
  17. }  

 

或者

class BinaryTreeNode{  
    int data;  
    BinaryTreeNode leftNode;  
    BinaryTreeNode rightNode;  
     
}

题目:输入两棵二叉树A和B,判断B是不是A的子结构。

例如图中所示的两棵二叉树,由于A中有一部分子树的结构和B 是一样的,因此B是A的子结构。

要查找树A中是否存在和树B结构一样的子树,我们可以分两步:第一步在树A中找到和B的根节点的值一样的结点R,第二步再判断树A中以R为根结点的子树是不是包含和树B一样的结构。

以上面的两棵树为例来详细分析这个过程。首先我们试着在树A中找到值 为8的结点。从树A的根节点开始遍历,我们发现它的根节点的值就是8.接着我们就去判断树A的根节点下面的子树是不是含有和树B一样的结构。在树A中,根 节点的左子结点的值是8,而树B的根节点的左子结点是9,对应的两个结点不同。

因此我们仍然要遍历A,接着查找值为8的结点。我们在树的第二层中找 到一个值为8 的结点,然后进行第二步的判断,即判断这个结点下面的子树是否含有和树B一样结构的子树。于是我们遍历这个结点下面的子树,先后得到两个子节点9和2,这 和树B的结构完全相同。此时我们在树A中找到了一个和树B的结构一样的子树,因此树B和树A的子结构。

在面试的时候,我们一定要检查边界条件,即检查空指针。当树A或树B为空的时候,定义相同的输出。如果没有检查并做响应的处理,程序非常容易崩溃,这是面试的时候非常忌讳的事情。

下面我们用Java代码来实现:

package cglib;
class BinaryTreeNode{  
    int data;  
    BinaryTreeNode leftNode;  
    BinaryTreeNode rightNode;  
     
}  


public class DeleteNode {
    public static void main(String args[])
    {
    BinaryTreeNode root1=new BinaryTreeNode();
    BinaryTreeNode node1=new BinaryTreeNode();
    BinaryTreeNode node2=new BinaryTreeNode();
    BinaryTreeNode node3=new BinaryTreeNode();
    BinaryTreeNode node4=new BinaryTreeNode();
    BinaryTreeNode node5=new BinaryTreeNode();
    BinaryTreeNode node6=new BinaryTreeNode();
    root1.leftNode=node1;
    root1.rightNode=node2;
    node1.leftNode=node3;
    node1.rightNode=node4;
    node4.leftNode=node5;
    node4.rightNode=node6;
    root1.data=8;
    node1.data=8;
    node2.data=7;
    node3.data=9;
    node4.data=2;
    node5.data=4;
    node6.data=7;
    BinaryTreeNode root2=new BinaryTreeNode();
    BinaryTreeNode a=new BinaryTreeNode();
    BinaryTreeNode b=new BinaryTreeNode();
    root2.leftNode=a;
    root2.rightNode=b;
    root2.data=8;
    a.data=9;
    b.data=2;
    DeleteNode test=new DeleteNode();
    System.out.println(test.hasSubTree(root1, root2));
    }
    
public boolean hasSubTree(BinaryTreeNode root1,BinaryTreeNode root2){
    
    boolean result=false;
   if(root1!=null&&root2!=null){
    if(root1.data==root2.data){//8,8
        result=doesTree1HavaTree2(root1,root2);
        if(!result)
        result=hasSubTree(root1.leftNode, root2);//看左结点8是不是等于头结点8
        if(!result)
        result=hasSubTree(root1.rightNode, root2);
        }
        }
        return result;//8,9不等
        }
        private boolean doesTree1HavaTree2(BinaryTreeNode root1, BinaryTreeNode root2) {
        if(root2==null){
        return true;
        }
        else if(root1==null)
            return false;
        if(root1.data!=root2.data){
        return false;
        }
        return doesTree1HavaTree2(root1.leftNode, root2.leftNode)&&
        doesTree1HavaTree2(root1.rightNode, root2.rightNode);//头结点相等,继续看左右两结点是不是相等
        }
}

 

转载于:https://my.oschina.net/u/2822116/blog/715363

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值