Check if two trees are identical - java

I've made my own Tree class and I trying to check if two trees are identical. But the problem here is I'm using this call :
Tree myTree = new Tree();
Tree mySecondTree = new Tree();
myTree.isIdentical(myTree, mySecondTree);
It's kind of odd to pass it this way, I want to pass it this way :
myTree.isIdentical(mySecondTree);
isIdentical function :
class Tree<T>{
T data;
Tree left;
Tree right;
Tree(T data){
this.data = data;
}
public boolean isIdentical(Tree t1, Tree t2){
if(t1 == t2)
return true;
if(t1==null || t2==null)
return false;
return (
(t1.data == t2.data) &&
(isIdentical(t1.left, t2.left)) &&
(isIdentical(t1.right, t2.right))
);
}
}
I tried using Stack, but I'm kind of stuck on this

Since you want to execute it this way
myTree.isIdentical(mySecondTree);
You could do this
public boolean isIdentical(Tree t2){
Tree t1 = this;
return isIdentical(t1, t2);
}
private boolean isIdentical(Tree t1, Tree t2){
if(t1 == t2)
return true;
if(t1==null || t2==null)
return false;
return (
(t1.data == t2.data) &&
(isIdentical(t1.left, t2.left)) &&
(isIdentical(t1.right, t2.right))
);
}

Your data-structure allows you to call the modified isIdentical(Tree<T>) method in the left and right child nodes after a few checks. Remember that the parent, right-child and left-child are all different Tree node instances in your code.
public boolean isIdentical(Tree<T> that) {
if (this == that)
return true;
if (that == null)
return false;
//check the equality of the current node's data for both this and that.
if (this.data == that.data || (this.data != null && this.data.equals(that.data))) {
//check the left hand side of the current node for both this and that.
if ((this.left == null && that.left == null
|| this.left != null && this.left.isIdentical(that.left))
//check the right hand side of the current node for both this and that.
&& (this.right == null && that.right == null
|| this.right != null && this.right.isIdentical(that.right))) {
return true;
}
}
return false;
}

You could stay with a recursion and make isIdentical(myTree, Othertree) private. Then wrap it inside a method IsIdentical(otherTree) that calls the method with two arguments suppling this (refrence to the current object) as the first parameter.

Related

check to see if tree has 0 or 2 children

How do I check to see if the entire tree is semi-perfectly has 0 or 2 nodes? Consider the following conditions:
A node with 0 children is semi-perfect.
A node with 1 child is NOT semi-perfect.
A node with 2 children is semi-perfect if
(size-of-larger-child <= size-of-smaller-child * 3)
This is what I have so far:
public static boolean isLeafOrHasTwoChildren(Node t) {
if (t.left == null && t.right == null) {
return true;
}
if (t.left == null || t.right == null) {
return false;
}
// Recurse down the tree
return isLeafOrHasTwoChildren(t.left)
&& isLeafOrHasTwoChildren(t.right);
}
Size computes the number of nodes in the tree.
Let's enumerate our conditions.
You return true if all visited nodes are null.
You return true if all visited nodes are defined.
You return false otherwise.
Let's identify the first condition - isLeaf - as:
boolean isLeaf = t.left == null && t.right == null;
Let's define hasAllChildren as:
boolean hasAllChildren = !(t.left == null || t.right == null);
If we look closely, !(t.left == null || t.right == null) is the same as t.left == null && t.right != null due to DeMorgan's Law. This allows us to express this fairly straightforwardly, and this is likely the piece you're missing.
Now, let's discuss recursive flow. We want to walk down the entire chain of nodes, in a visit-left-right fashion. So, we want to check our conditions before we recurse.
Base case: If we're not a leaf (implying we don't have all children), we return false immediately.
Recursive step: If we're a leaf or we have all children, we continue down the chain.
Let's try to express this.
public static boolean isLeafOrHasTwoChildren(Node t) {
// Trivial case; if we have an undefined node, we've definitely reached a leaf.
if (t == null) {
return true;
}
boolean isLeaf = t.left == null && t.right == null;
boolean hasAllChildren = !(t.left == null || t.right == null);
if(isLeaf || hasAllChildren) {
return isLeafOrHasTwoChildren(t.left) && isLeafOrHasTwoChildren(t.right);
} else {
return false;
}
}

Test if two binary trees are equal

I know this may be a duplicate post, but I would submit my own code to your attention.
I wrote the following recursive procedure, but I would like to optimize it.
I would like to stop the treeCompare method as soon as I find a node different from other, instead of comparing all nodes.
Thanks in advance for your help.
This is my thin Node class:
public class Node {
public Node father;
public Node left;
public Node right;
}
And this is my comparator method:
private boolean treeCompare(Node firstNode, Node secondNode) {
if (firstNode == null && secondNode == null)
return true;
else if (firstNode == null || secondNode == null)
return false;
boolean isLEquals = treeCompare(firstNode.left, secondNode.left);
boolean isREquals = treeCompare(firstNode.right, secondNode.right);
return firstNode.equals(secondNode) && isLEquals && isREquals;
}
private boolean treeCompare(Node firstNode, Node secondNode) {
if (firstNode == secondNode)
return true;
if (firstNode == null || !firstNode.equals(secondNode))
return false;
return treeCompare(firstNode.left, secondNode.left) && treeCompare(firstNode.right, secondNode.right);
}

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

Recursive compare two binary search trees

I need to compare two binary search trees and see if they are equal or not.
I developed following code that uses recursion.
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if(n1.getNodeData() != n2.getNodeData())
return false;
else
{
if(n1.left != null && n2.left != null)
compareTrees(n1.left, n2.left);
if(n1.right != null && n2.right != null)
compareTrees(n1.right, n2.right);
}
return true;
}
The problem is that if two nodes are not equal, the method will return false but because I use recursion, the return value will be overridden to true no matter what. I have been stuck with this problem for all day and nothing worked for me. I searched online but I didn't find anything relevant to my code.
Is there any way to break from all nested methods and return value to the first method?
You need to return the result of the subtree comparison:
boolean b1, b2;
if(n1.left != null && n2.left != null)
b1 = compareTrees(n1.left, n2.left);
if(n1.right != null && n2.right != null)
b2 = compareTrees(n1.right, n2.right);
return b1 && b2;
But why not just deal with nulls before-hand?
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if (n1 == null || n2 == null)
return n1 == n2; // i.e. both null
if (n1.getNodeData() != n2.getNodeData())
return false;
return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);
}
I would do it changing the order:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
boolean equalLeft = false;
boolean equalRight = false;
if(n1.getNodeData() == n2.getNodeData())
{
if(n1.left != null && n2.left != null){
equalLeft = compareTrees(n1.left, n2.left);
} else{
equalLeft = true;
}
if(n1.right != null && n2.right != null){
equalRight = compareTrees(n1.right, n2.right);
} else{
equalRight = true;
}
return equalLeft && equalRight;
} else{
return false;
}
}
Try to face the problem avoiding null values and using equals() method instead of == comparison for your nodes. I shoud do it this way:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2){
//avoid nulls :TDD
if (n1==null && n1==n2)
return true;
if ((n1==null && n2!=null) || (n2==null && n1!=null))
return false;
//ensure logic without nulls, comparing with equals() method
boolean areEquals = n1.getNodeData().equals(n2.getNodeData());
//compare left
areEquals = areEquals && compareTrees(n1.left, n2.left);
//if still equals, compare right
if(areEquals) areEquals = areEquals && compareTrees(n1.right, n2.right);
return areEquals;
}
Effectively, your code could reduce to:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if(n1==null || n2==null) return n1==n2;
return (n1.getNodeData()==n2.getNodeDate()) && compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right)
}
I will tell you couple of problems your code has.
Termination criteria when root is null (it will always happen in the end).
Return statements in recursive calls. You are always returning the true in the end.
PS: If you add NULL checks (explained in 1), you need not to add null checks in the subsequent recursive calls. Now the second half of your code will look like:
return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);

Recursively searching binary tree issue

I have written the below code for recursively searching binary tree .
Even though my system.out statement is getting executed , the return statement is not returning out of entire recursion and thus this method not returning true.
Can anyone suggest how can I return out of entire recursion.?
public static boolean isElementinTree(int num, BinaryTreeNode root)
{
if (root != null)
{
int rootVal = root.getData();
BinaryTreeNode left = root.getLeft();
BinaryTreeNode right = root.getRight();
if (left != null)
{
isElementinTree(num,left);
}
if (right != null)
{
isElementinTree(num,right);
}
if (num == rootVal)
{
System.out.println("------ MATCH -----");
return true;
}
}
return false;
}
This is the problem:
if (left != null)
{
isElementinTree(num,left);
}
if (right != null)
{
isElementinTree(num,right);
}
You're calling the method in those cases - but ignoring the result. I suspect you just want to change each of those to return immediately if it's found:
if (left != null && isElementinTree(num, left))
{
return true;
}
if (right != null && isElementinTree(num, right))
{
return true;
}
Or to make the whole thing more declarative, you can do it more simply:
public static boolean isElementinTree(int num, BinaryTreeNode root)
{
return root != null && (root.getData() == num ||
isElementInTree(num, root.getLeft()) ||
isElementInTree(num, root.getRight()));
}
It's fine to call isElementInTree with a null second argument, as you're already protecting against that with the first part.
What is wrong with a simple solution like this:
public static boolean isElementinTree(int num, BinaryTreeNode root)
{
return root != null && //The tree is non-null
(num == root.getData() || //We have num in this node OR
isElementInTree(num, root.getLeft()) || //We have num in left subtree OR
isElementInTree(num, root.getRight()) ); //We have num in right subtree
}
You need to check if the value is in one of the branches, and save that result.
Initialize a variable boolean found = false;.
When you do the recursive call, you need to do something like:
found = isElementinTree(num,left)
same thing for the right side.
At the end, instead of returning false, check if the value was found on a branch, simply return found;
Also, first check if the number you are looking for isn't on the Node itself, instead of searching each branch first. Simply switch the order of the if's.
If you do find the element you're looking for in the left or right subtrees you need to return this fact back up to the caller:
if (left != null)
{
if(isElementinTree(num,left)) return true;
}
if (right != null)
{
if(isElementinTree(num,right)) return true;
}
Only if you find it in none of the left tree, right tree and current node do you eventually fall through to the final return false.
Recursion solution:
boolean isElementinTree (int num, BinaryTreeNode root)
{
if(root == null)
return false;
if(root.value == num)
return true;
boolean n1 = isElementinTree(num,root.getLeft());
boolean n2 = isElementinTree(num,root.getRight());
return n1 ? n1 : n2;
}

Categories