I'm coding a program and i need to know if a BST is symmetric in its structure
public void traverse (Layer root){
if (root.leftChild != null){
traverse (root.leftChild);
}
if (root.rightChild != null){
traverse (root.rightChild);
}
I have the traverse code but i dont know how to check if it is symmetric
Thanks for the help
I learned how to do this during school, and this is what I did. I learned it from a website I can't remember, but I kept the comments in it.
boolean isMirror(Node node1, Node node2)
{
// if both trees are empty, then they are mirror image
if (node1 == null && node2 == null)
return true;
// For two trees to be mirror images, the following three
// conditions must be true
// 1 - Their root node's key must be same
// 2 - left subtree of left tree and right subtree
// of right tree have to be mirror images
// 3 - right subtree of left tree and left subtree
// of right tree have to be mirror images
if (node1 != null && node2 != null && node1.key == node2.key)
return (isMirror(node1.left, node2.right)
&& isMirror(node1.right, node2.left));
// if neither of the above conditions is true then
// root1 and root2 are mirror images
return false;
}
boolean isSymmetric(Node node)
{
// check if tree is mirror of itself
return isMirror(node, node);
}
public boolean isSymmetric(Layer root) {
return root == null || isSymmetric(root.left, root.right);
}
public boolean isSymmetric(Layer left, Layer right) {
if (left == null && right == null) return true;
return left != null && right != null && left.val == right.val && isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left);
}
I suppose that you mean that tree is symmetric if it is form a "mirror" of itself
Related
I'm currently in the middle of an AVL Tree insert implementation, and I am struggling with maintaining the balance factors while inserting and backtracking up the tree.
Virtually every AVL implementation I can find as an example uses the height of a node's two sub-tree's to calculate the balance factor, something along the lines of
node.balance = node.right.height - node.left.height
And this is perfectly fine if your Node class looks something like
class Node {
int value, height;
Node left, right;
}
Though the problem is that for this particular implementation, it is 'against the rules' to keep track of the height of the node, and instead we can only keep track of the balance factor. So the Node class instead looks like
class Node {
int value, balance;
Node left, right;
}
I know that maintaining the balance factor of a node is conceptually similar to maintaining the height for each insert into the tree, but for the life of me I can't figure out all of the situations in which the balance factor should change for a particular node.
At the moment I've got setting the balance factor implemented by instead recursively calling the height function for each and every node ( not optimal! ) to make sure my rotations and general insertion is correct.
node.balance = height(node.right) - height(node.left)
Where height() recursively traverses the tree to find the longest path to a leaf.
And I have verified that the rotation logic is indeed correct, but when I start writing code to maintain the balances by +-1 increments backtracking up the tree, the code immediately turns into spaghetti, as I am clearly not understanding something fundamental about the node balance factor.
If you want to see that code, I've posted it below ( its a bit long ). And the below implementation is also a String AVL Tree, but the idea is the same.
Any input is appreciated, Thanks!
class StringAVLNode {
private String item;
private int balance;
private StringAVLNode left, right;
// just one constructor, please
public StringAVLNode(String str) {
item = str;
balance = 0;
left = null; right = null;
}
public int getBalance () {
return balance;
}
public void setBalance ( int bal){
balance = bal;
}
public String getItem () {
return item;
}
public StringAVLNode getLeft () {
return left;
}
public void setLeft (StringAVLNode pt){
left = pt;
}
public StringAVLNode getRight () {
return right;
}
public void setRight (StringAVLNode pt){
right = pt;
}
public void insert(String str) {
root = insert(str, root);
}
private StringAVLNode insert(String str, StringAVLNode t) {
// Base case - Just insert the node
if (t == null)
t = new StringAVLNode(str);
else {
int balance, leftChildBalance, rightChildBalance;
leftChildBalance = t.getLeft() != null ? t.getLeft().getBalance() : -99;
rightChildBalance = t.getRight() != null ? t.getRight().getBalance() : -99;
// Perform string comparisons to determine left/right insert
int compareResult = str.compareToIgnoreCase(t.getItem());
if (compareResult < 0) {
t.setLeft(insert(str, t.getLeft()));
if (t.getRight() == null)
t.setBalance(t.getBalance()-1);
else if (leftChildBalance == 0 && t.getLeft().getBalance() != 0)
t.setBalance(t.getBalance()-1);
else if (leftChildBalance == -99 && t.getLeft() != null)
t.setBalance(t.getBalance()-1);
}
else if (compareResult > 0) {
t.setRight(insert(str, t.getRight()));
if (t.getLeft() == null)
t.setBalance(t.getBalance()+1);
else if (rightChildBalance == 0 && t.getRight().getBalance() != 0)
t.setBalance(t.getBalance()+1);
else if (rightChildBalance == -99 && t.getRight() != null)
t.setBalance(t.getBalance()+1);
}
balance = t.getBalance();
// Verbosify booleans
boolean rightImbalance = balance > 1; boolean leftImbalance = balance < -1;
// Imbalance tree situation calls balanceTrees() to handle the rotation logic
// ( Keeps insert() succinct )
if (rightImbalance || leftImbalance)
t = balanceTrees(balance, t);
}
return t;
}
// Rotation Handler
private StringAVLNode balanceTrees(int balance, StringAVLNode t) {
// Verbosify boolean values
boolean rightHeavy = balance > 1; boolean leftHeavy = balance < -1;
boolean requiresDoubleLeft = t.getRight() != null && t.getRight().getBalance() <= -1;
boolean requiresDoubleRight = t.getLeft() != null && t.getLeft().getBalance() >= 1;
if (rightHeavy) {
/** Do double left rotation by right rotating the right child subtree, then
* rotate left
*/
if (requiresDoubleLeft) {
t.setRight(rotateRight(t.getRight()));
t.getRight().setBalance(0);
t = rotateLeft(t);
t.setBalance(0);
}
else {
t = rotateLeft(t);
t.setBalance(0);
if (t.getLeft() != null) t.getLeft().setBalance(0);
if (t.getRight() != null) t.getRight().setBalance(0);
}
}
/** Do double right rotation by left rotating the left child subtree, then
* rotate right
*/
else if (leftHeavy) {
if (requiresDoubleRight) {
t.setLeft(rotateLeft(t.getLeft()));
t.getLeft().setBalance(0);
t = rotateRight(t);
t.setBalance(0);
}
else {
t = rotateRight(t);
t.setBalance(0);
if (t.getLeft() != null) t.getLeft().setBalance(0);
if (t.getRight() != null) t.getRight().setBalance(0);
}
}
if (t.getLeft() != null) {
if (t.getLeft().getRight() != null && t.getLeft().getLeft() == null)
t.getLeft().setBalance(1);
else if (t.getLeft().getLeft() != null && t.getLeft().getRight() == null)
t.getLeft().setBalance(-1);
else if ((t.getLeft().getLeft() != null && t.getLeft().getRight() != null)
|| (t.getLeft().getLeft() == null && t.getLeft().getRight() == null))
t.getLeft().setBalance(0);
}
if (t.getRight() != null) {
if (t.getRight().getRight() != null && t.getRight().getLeft() == null)
t.getRight().setBalance(1);
else if (t.getRight().getLeft() != null && t.getRight().getRight() == null)
t.getRight().setBalance(-1);
else if ((t.getRight().getLeft() != null && t.getRight().getRight() != null)
|| (t.getRight().getLeft() == null && t.getRight().getRight() == null))
t.getRight().setBalance(0);
}
return t;
}
}
Check out my AVL Tree in Java writeup at:
https://debugnotes.wordpress.com/2015/01/07/implementing-an-avl-tree-in-java-part-2
It appears that your implementation does not include any kind of stack based element (recursive or array based) to keep track of how deep you are in the tree. This is a key part of being able to navigate self-balancing tree data structures - being able to search downwards, find and do something with a target node, and then trace backwards to the root node of the tree where it started navigating from, manipulating it as you work your back way up. Using recursion is one way (i.e. using the program stack) or you need to implement your own stack (e.g. use a Queue or LinkedList) but unless your code has a memory structure recording where it's been, unfortunately it'll always get lost.
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;
}
}
I've found a solution to this problem, in this code,
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;
if(root == p || root == q) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
return left != null && right != null ? root : left == null ? right : left;
}
I just can't seem to understand the last line. Can someone help me understand how the code works in the last line.
I assume you're aware this makes use of the ternary operator.
It might be easier to understand if you saw it surrounded with parenthesis:
return (left != null && right != null ? root : (left == null ? right : left));
Meaning, this could be rewritten as the following nested if:
if (left != null && right != null) {
return root;
} else {
if (left == null) {
return right;
} else {
return left;
}
}
So let's break it down. You've already checked recursively the left child sub-tree and the right child sub-tree. Now you need to decide which node you're going to return.
If both children exist (left != null && right != null), then the lowest common ancestor of both sub-trees is the current node, meaning the root, which is why you return it.
If however, one of the sub-trees doesn't exist, for instance in the following case when looking at node2 who only has one child:
root
/ \
node1 node2
/ \ \
node3 node4 node5
Then the root cannot be the lowest common ancestor, which means it has to be in one of the sub-trees. Since one of them is null (doesn't exist), then it has to be in the other.
So if left == null then return the lowest common ancestor you've found on the right sub-tree, otherwise the right-subtree doesn't exist (is null) and so return the lowest common ancestor you've found on the left sub-tree.
The ternary operator is used to determine which value is returned. It mighy be a bit clearer if you set braces appropriatly:
return (left != null && right != null) ? root : ((left == null) ? right : left);
Alternatively, you can rewrite the statement to use if's, which might make it a bit clearer:
if (left != null && right != null) {
return root;
} else {
if (left == null) {
return right;
} else {
return left;
}
}
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.
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;
}