比較兩棵二叉樹是否相同/一棵二叉樹是否是另一棵二叉樹的子樹/一棵二叉樹是否是另一顆二叉樹的子結構


本文章討論兩個問題:

①如何判斷兩棵二叉樹的結構是一樣的、對應的每個結點都有着相同的值。--即判斷兩棵二叉樹是一樣的

②給定兩棵二叉樹,如何判斷一棵二叉樹是另一棵二叉樹的子結構

③給定兩棵二叉樹,如何判斷一棵二叉樹是另一棵二叉樹的子樹

注意,子結點與子樹不同。如下圖所示,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 }

 另外拓展:三種遍歷序列中,中序遍歷+前序/后序即可重建二叉樹。但是只有前序和后序遍歷序列無法重建二叉樹。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM