简体   繁体   中英

Search if a binary-tree is subtree of another binary-tree

I have a serious problem with recurive search of subtree in onether one.

I try this but...

public static boolean containsTree (Node t1, Node t2)
{
    if (t2 == null)
        return true;
    // Empty tree is always a subtree.
    else
        return subTree(t1, t2);
}

public static boolean subTree (Node t1, Node t2)
{
    if (t1 == null)
        return false; // Big tree is over.
    if (t1.getName().equalsIgnoreCase(t2.getName()))
        return matchTree(t1, t2);
    return (subTree(t1.getChild(), t2) || subTree(t1.getBrother(), t2));
}

private static boolean matchTree (Node t1, Node t2)
{
    if (t1 == null && t2 == null)
        return true; // Both trees are empty.
    if (t1 == null || t2 == null)
        return false; // Big tree empty and subtree still not found.
    if (!t1.getName().equalsIgnoreCase(t2.getName()))
        return false;
    return (matchTree(t1.getChild(), t2.getChild()) && matchTree(
            t1.getBrother(), t2.getBrother()));
}

seems to be not correctly formed. the containsTree function, stop to search when find a node that is different from onether one.

Below, you can find an example of two tree.

          1                 
         / \                                    3
        /   \                                   /\
       /     \                                 /  \
      2      3                                7    8
      /\     /\
     /  \   /  \
     3   4 5    6
                 \
                  3
                  /\
                 /  \
                 7   8

In this case when the function compare the subtree on the right with subtree on the left, it stop to search when find equals parent node but it have different child node. I need that the function don't stop to search but go throw this point and search for all other child node and their subtree.

say our class is like this:

class Node{
    node left, right;
    int value;    

    boolean equals(Node n){
        // if one child is null we can skip
        if(this.left == null && this.left != null ||
           this.left != null && this.left == null ){
            return false;
        }
        if(this.right == null && this.right != null ||
           this.right != null && this.right == null ){
            return false;
        }
        // 
        return (this.value == n.value) && 
               ( this.left == null || (this.left.equals(n.left)) ) && 
// if this.left == null, n.left is null too and the || will skip the equals()
               ( this.right == null || (this.right.equals(n.right)) );
// same for right
    }
}

this method will recursively check if a tree looks the same as another so, lets check if its a subtree:

boolean isSubTree(Node other){
    return this.equals(other) || 
         (other.left != null && this.isSubTree(other.left)) || 
// if left is null, this cant be a subtree 
         (other.right != null && this.isSubTree(other.right));
// same for right
}

Nothing tested but i think it could be work like this. I skipped constructors and other functions.

(bit overloaded return statements :P )

you should keep some things in your mind: trees are usually used to search for values, and are mostly implemented as binary trees were: left-child < parent < right-child

edit

obviously you should make sure that your tree does not circle :P

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM