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.
Related
I am having trouble figuring out how to set a variable "minData" to the minimum value inserted into a binary search tree. If I am thinking of this correctly, the most minimum value in the tree will always be in the left subtree so my code for setting this minimum value should go under the "else if (root.data < data)" statement. I also don't know how to access the minData variable inside my insert method. My code so far is:
private class Node {
int key;
int data;
int minData;
private Node left;
private Node right;
private Node root;
Node(int data) {
this.data = data;
left = null;
right = null;
root = null;
}
}
public TheBST(Node root) {
root = null;
}
public void insert(Node root, int data) {
Node newNode = new Node(data);
if(root == null) {
Node node = new Node(data);
root = node;
}
else if(root.data > data) {
if(root.left == null) {
Node node = new Node(data);
root.left = node;
}
insert(root.left, data);
}
else if(root.data < data) {
if(root.right == null) {
Node node = new Node(data);
root.right = node;
return;
}
insert(root.right, data);
}
}
Your forming of BST is not accurately done. You need to return from the method (or stack fragment of memory in case recursive procedure) when you would actually find the place to insert.
Add the return statement for the left-subtree:
else if(root.data > data) {
if(root.left == null) {
Node node = new Node(data);
root.left = node;
return;
}
insert(root.left, data);
}
Which is you are doing in case of the right-subtree.
P.S: once you are done with tree insertion, you can return the left-most-node from left-subtree, it would have the minimum value.
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++;
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)
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..
I know there are a lot of similar questions on here. I've looked at them, but everyone's implementation is different and it's just confusing me. I am trying to make a binary tree. Every time I insert an element, it becomes the root which is not what I want. If I try to access the data at the root from the main method or pass the root into another method, I get a null pointer exception. Can anyone tell me why my root is always null and why my insert method is not assigning a value to the root? Any tips on better design for data structures in Java would also be much appreciated.
package interviewQuestions;
public class BinaryTree {
private Node root = null;
private class Node {
int data;
Node left;
Node right;
public Node(int dataval){
data = dataval;
left = null;
right = null;
}
}
// A binary search tree must have no duplicate nodes
// Insert nodes into the tree. Return 1 on success.
public int insert(Node root, int data){
Node temp = root;
if(root == null){
Node node = new Node(data);
root = node;
System.out.println("new root is "+root.data);
return 1;
}
else if(temp.data < data && temp.right != null){
if(data < temp.right.data){
Node node = new Node(data);
node.right = temp.right;
temp.right = node;
return 1;
}
else{
temp = temp.right;
insert(temp, data);
}
}
else if(temp.data < data && temp.right == null){
Node node = new Node(data);
temp.right = node;
return 1;
}
else if(temp.data > data && temp.left != null){
if(data > temp.left.data){
Node node = new Node(data);
node.left = temp.left;
temp.left = node;
return 1;
}
else{
temp = temp.left;
insert(temp, data);
}
}
else if(temp.data > data && temp.left == null){
Node node = new Node(data);
temp.left = node;
return 1;
}
return -1;
}
public void preOrder(Node root){
if(root.left != null){
System.out.println(root.data);
root = root.left;
preOrder(root);
}
else if(root.left == null && root.right != null){
System.out.println(root.data);
root = root.right;
preOrder(root);
}
else if(root.left == null && root.right == null){
return;
}
}
// Remove
// Find
// Balance
public static void main (String[] args){
BinaryTree tree = new BinaryTree();
tree.insert(tree.root, 5);
tree.insert(tree.root, 2);
tree.insert(tree.root, 8);
tree.insert(tree.root, 1);
tree.insert(tree.root, 3);
tree.insert(tree.root, 9);
tree.insert(tree.root, 20);
tree.insert(tree.root, 10);
tree.insert(tree.root, 15);
System.out.println(tree.root);
tree.preOrder(tree.root);
System.out.println("Ya. everysing ees güten tag. YA.");
}
}
You are passing in a root variable when root is a private variable in your class. Fix your insert statement to only receive data and change private variable root to equal node.
Your method causes it to set the parameter root to node. This results in no change to the classes root.
You don't need to change the visibility of the root. When you enter the insert statement you have 2 different root variables in your code; the root you declared in your class and the root you passed as a parameter. You only want the one in the class