Recursively filling the height of a Binary Search Tree? - java

I have a homework problem that asks to write a method that recursively fills in the height of a binary search tree.
Below is my code
I checked the answer key for this problem and it made sense, but I wanted to know if my method is another valid way of doing this or not.
public static <T extends Comparable> void fillsHeight(BSTNode root){
if (root == null) return;
if (root.left == null && root.right == null) root.height = 0;
if (root.left != null) height = root.left.height + 1;
if (root.right != null) height = Math.max(height, root.right.height) + 1;
fillsHeight(root.left);
fillsHeight(root.right);
}
And below is the official solution from the answer key:
public static <T extends Comparable>
void fillHeights(BSTNode root) {
if (root == null) { return; }
fillHeights(root.left);
fillHeights(root.right);
root.height = -1;
if (root.left != null) {
root.height = root.left.height;
}
if (root.right != null) {
root.height = Math.max(root.height, root.right.height);
}
root.height++;
}

The importance from the solution is that it first calls recursively to the root left and right subtree with fillHeights(root.left); and fillHeights(root.right);, and only after that compares the results.
You are also missing the vital part of actually adding to the height of the nodes, with root.height++;

Related

Finding the height of a binary tree

I wrote the following code for finding the height of the binary tree, this is wrong, its failing the test cases, but why it is wrong, how to prove logically that this is wrong?
// WRONG CODE
public static int height(Node root) {
if(root != null){
if(root.left != null && root.right != null){
return Math.max(height(root.left), height(root.right)) + 1;
}else if(root.left != null){
return height(root.left);
}else{
return height(root.right);
}
}
return 0;
}
Whereas this following code is right!!
//RIGHT WORKING CODE
public static int height(Node root) {
if(root != null){
if(root.left != null || root.right != null){
return Math.max(height(root.left), height(root.right)) + 1;
}
}
return 0;
}
What is the big difference between the two codes that makes one of them right and other the wrong one?
For clarity the class code for the Node is added here.
class Node {
Node left;
Node right;
int data;
Node(int data) {
this.data = data;
left = null;
right = null;
}
}
And this is the logic to insert a node into the binary tree.
public static Node insert(Node root, int data) {
if(root == null) {
return new Node(data);
} else {
Node cur;
if(data <= root.data) {
cur = insert(root.left, data);
root.left = cur;
} else {
cur = insert(root.right, data);
root.right = cur;
}
return root;
}
In the second and third cases (just a left node, or just a right node) you're not adding one to account for the node you're currently on.
By the way your code also has a potential bug, in that it's possible for both left and right to be null. Your height function can handle null so really none of this checking is necessary, except for the check on the first line of the height function itself. But if it's important to check for null in the second case, then you should check for null in the third case too.

AVL Tree Implementation - Without Storing Height

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.

Returning deleted node from binary search tree

I'm attempting to write a method that would remove node from BST by the given value and I need it to return this deleted value. I found assorted examples of recursive implementations, but because of their nature, they can't return deleted node, but rather the root. Here's what I have now
public TreeNode remove(TreeNode node, int data) {
if (null == node) {
return null;
}
if (data < node.st.getkey()) {
node.left = remove(node.left, data);
} else if (data > node.st.getkey()) {
node.right = remove(node.right, data);
} else { // case for equality
if (node.left != null && node.right != null) {
TreeNode minInRightSubTree = min(node.right);
copyData(node , minInRightSubTree);
node.right = remove(node.right, minInRightSubTree.st.getkey());
} else {
if (node.left == null && node.right == null) {
node = null;
} else {// one child case
TreeNode deleteNode = node;
node = (node.left != null) ? (node.left) : (node.right);
deleteNode = null;
}
}
}
return node;
}
Can I come up with some hack to make it return deleted node or should I look into iterative algorithm( and if so I would really appreciate it if you could hook me up with the link).
You can return not just root but a pair of root and deleted node (or null if nothing was deleted).
You can use Map.Entry or new class to store 2 fields (I would recommend new class since it's more descriptive).
So your possible new signature will be public Map.Entry<TreeNode, TreeNode> remove(TreeNode node, int data)

Remove element from Binary Search Tree

I am doing an assignment, implementing own Binary Search Tree. The thing is, we have our own implementation of Node its parent is not directly accessible.
I have searched for answers, but I do not want to copy the solution entirely and I still don't seem to get it right, though. I miss some cases when the element is not removed.
Can you please help what am I doing wrong?
This is the remove method:
void remove(E elem) {
if(elem != null){
if (root != null && contains(elem)) {
removeFromSubtree(elem, root, null);
}
}
}
void removeFromSubtree(E elem, Node<E> current, Node<E> parent) {
if(elem.less(current.contents)){
if(current.left == null) return ;
removeFromSubtree(elem, current.left, current);
} else if(elem.greater(current.contents)){
if(current.right == null)return;
removeFromSubtree(elem, current.right, current);
} else {
if(current.left != null && current.right != null){
//both children
if(parent == null){
Node<E> n = new Node<>(null, null);
n.left = root;
removeFromSubtree(root.contents, n, null);
root = n.left;
root.setParent(null);
}
E min = subtreeMin(current.right);
current.contents = min;
removeFromSubtree(min, current.right, current);
} else if(current.left != null){
//left child
if (parent == null) {
root = current.left;
current.left.setParent(null);
return ;
}
setParentChild(current, parent, current.left);
} else if(current.right != null){
//right child
if (parent == null) {
root = current.right;
current.right.setParent(null);
return ;
}
setParentChild(current, parent, current.right);
} else {
if (parent == null) {
root = null;
return ;
}
setParentChild(current, parent, null);
}
}
}
Nodes use generic interface
class Node<E extends DSAComparable<E>>
which has just methods for comparation. It looks like this
interface DSAComparable<E extends DSAComparable<E>> {
boolean less(E other);
boolean greater(E other);
boolean equal(E other);
}
I use another methon inside remove that sets node's parent's child, depending if its left child or right child.
void setParentChild(Node<E> node, Node<E> parent,Node<E> value){
if(parent!= null){
if (parent.left == node) {
parent.left = value;
} else {
parent.right = value;
}
if(value!= null) value.setParent(parent);
}
}
Method subtreeMin(Node node) finds the smallest value in a subtree (the most left one)
Understanding your code is not so easy, since it still lacks of details.
I would refer to such an implementation of the Binary Search Tree that you can find online.
See for instance the one from Algorithms, 4th Ed..

Getting the next leafnode in a binary search tree using an iterator

I have some problems when it comes to the next()-method in my LeafNodeIterator-class.
First of all a leaf node is a node with no children in a binary search tree.(Not sure if leafnode is the right english word for it...)
In the constructor I've moved my pointer p to the first leafnode using this method:
private BladnodeIterator() // constructor
{
if(root == null) return;
firstleafnode(root);
}
private void firstleafnode(Node<T> p)
{
while(p != null)
{
if(p.left == null && p.right == null)
return;
p = nextInorder(p);
}
}
The "nextInorder(p)"-method just moves p to the next Node in Inorder-order.
My question when it comes to the next()-method, which is supposed to return a leafnode-value, and move p to the next leafnode(or null if there are no more leafnodes), is how to code it? Either way I try it I end up doing it wrong.
My apologies if the question or code is unclear.
EDIT:
The code for the nextinorder-method:
private static <T> Node<T> nextInorder(Node<T> p)
{
if(p.right != null)
{
p = p.right;
while(p.left != null)
{
p = p.left;
}
return p;
}
while(p != null)
{
if(p.parent != null && p.parent.left == p)
{
return p.parent;
}
p = p.parent;
}
return p;
}

Categories