比较两棵二叉树是否相同/一棵二叉树是否是另一棵二叉树的子树/一棵二叉树是否是另一颗二叉树的子结构

本文章讨论两个问题:

①如何判断两棵二叉树的结构是一样的、对应的每个结点都有着相同的值。--即判断两棵二叉树是一样的

②给定两棵二叉树,如何判断一棵二叉树是另一棵二叉树的子结构

③给定两棵二叉树,如何判断一棵二叉树是另一棵二叉树的子树

注意,子结点与子树不同。如下图所示,2,3,4都是1的子结构但是只有4是1的子树。

 

一、判断两个二叉树是否完全一致

(1)由于先序序列和中序序列可以完全确定一颗二叉树,因此可以将两个二叉树的先序序列和中序序列求出来,然后比较二者是否一致。

(2)递归,比较根结点是否一样;如果根结点一样,再继续比较根的左右孩子是否一样。

 1 public boolean sameTree2(BinaryNode<T> root1, BinaryNode<T> root2){
 2         //树的结构不一样
 3         if((root1 == null && root2 != null) || (root1 != null && root2 == null))
 4             return false;
 5         
 6         //两棵树最终递归到终点时
 7         if(root1 == null && root2 == null)
 8             return true;
 9         
10         if(root1.element.compareTo(root2.element) != 0)
11             return false;
12         else
13             return sameTree2(root1.left, root2.left) && sameTree2(root1.right, root2.right);
14     }

二、一棵二叉树是否是另一棵二叉树的子树

错误解法:此时不可以用得到两棵树的先序(中序、后序)遍历序列1、2,然后利用KMP算法判断2是否是1的子序列。

原因:因为一个序列不能唯一构建一棵二叉树,如下图所示,1的先序遍历序列为 ABDEC,2的先序遍历序列为BDE,但是2不是1的子树。、

与判断是否是子结构类似,只是在isSubtree的递归出口有些差别。

//判断以当前root1为根的树,和以root2为根的树,是否是相同的树
    public static boolean isSubtree(TreeNode root1,TreeNode root2) {
        if(root1==null&&root2!=null)
            return false;
        if(root1!=null&&root2==null)
            return false;
        if(root2==null&&root1==null)
            return true;
        if(root1.val==root2.val)
        {
            return isSubtree(root1.left,root2.left)&&isSubtree(root1.right,root2.right);
        }
        else
            return false;
    }

三、一棵二叉树是否是另一颗二叉树的子结构

错误解法:判断子结构问题同样不能用子序列的方式进行,如图所示。

原因1: 是子结构,不一定是子序列。 树1先序遍历 ABDEC,树3先序遍历ABC,3是1的子结构,但是序列不是其子序列。

原因2:是子序列,不一定是子结构。如问题二图所示。

 1 /**
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 public class Solution {
15     //判断以当前root1为根的树,和以root2为根的树,是否是根相同的子结构
16     public static boolean isSubtree(TreeNode root1,TreeNode root2) {
17         if(root1==null&&root2!=null)
18             return false;
19         if(root2==null)
20             return true;
21         if(root1.val==root2.val)
22         {
23             return isSubtree(root1.left,root2.left)&&isSubtree(root1.right,root2.right);
24         }
25         else
26             return false;
27     }
28     
29     //只用一个函数,由于需要递归,递归出口与判断初始树是否为空矛盾。
30     //此函数当前节点不相等则继续比较左右子树,与上面的函数不同
31     //将判断当前子树与目标子树是否相同作为一个单独的函数(isSubtree)。
32     public static boolean HasSubtree(TreeNode root1,TreeNode root2) {
33         if(root1==null&&root2!=null)
34             return false;
35         if(root2==null)
36             return false;   //空树不是任一树的子结构
37         boolean tag=false;
38         tag=isSubtree(root1,root2);
39         if(tag==true)
40             return true;
41         else{
42             tag=HasSubtree(root1.left,root2);    //此处的函数调用为HasSubtree,因为isSubtree只判断当前根节点相同的子结构,不会递归判断子树
43             if(tag==true)
44                 return true;
45             else
46                 return HasSubtree(root1.right,root2);
47         }
48     }
49 }

 另外拓展:三种遍历序列中,中序遍历+前序/后序即可重建二叉树。但是只有前序和后序遍历序列无法重建二叉树。

原文地址:https://www.cnblogs.com/simpleDi/p/11430202.html