I need to write a method to delete a node from a binary tree. I tried reading and making use of other people's questions, kind of helped. Thing is I get some errors. I'm kind of confused.
Here is the code:
String delete(int k)
{
BSTNode maxfromleft = null;
BSTNode n = getNode(k);
BSTNode n1 = n;
if(n == null)
return null;
if (k < node.getKey())
n.left.setValue(delete(n.left.getKey()));
else if(k > node.getKey()){
n.right.setValue(delete(n.right.getKey()));
}
else{
if(n.right != null && n.left != null){
maxfromleft = max(n.left);
n.left.setValue(delete(n.left.getKey()));
n.setValue(maxfromleft.getValue());
}
else if(n.right == null){
n = n.left;
return n1.getValue();
}
else if(n.left == null){
n = n.right;
return n1.getValue();
}
}
return n.getValue();
}
private BSTNode max(BSTNode n) {
if (n == null)
return null;
if (n.right != null)
return max(n.right);
return n;
}
I get a NullPointerException error at this line:
n.left.setValue(delete(n.left.getKey()));
why?
How can I fix this?
All help is appreciated :)
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
Ok, so I wanted to write a delete method that works for any "delete-case" for Binary Search Trees and this is my attempt:
public void delete(int key) {
if (root.value == key) {
root = root.right;
root.left = root.right.left;
return;
}
else {
deleteRecursive(key, root); ***LINE 58***
}
}
public void deleteRecursive(int key, BinaryNode node) {
if (node == null) {
System.out.println("ERROR");
return;
}
else {
if (key < node.value) {
// continue search on left
if (node.left.value == key) {
if (node.left.left == null && node.left.right == null) {
node.left = null;
}
else if (node.left.left == null){
node.left = node.left.right;
}
else if (node.left.right == null){
node.left = node.left.left;
}
else{
node.left = node.left.right;
node.left.left = node.left.right.left; ***LINE 83***
}
}
else {
deleteRecursive (key, node.left);
}
}
else if (key > node.value){
// continue search on right
if (node.right.value == key) {
if (node.right.left == null && node.right.right == null) {
node.right = null;
}
else if (node.right.left == null){
node.right = node.right.right;
}
else if (node.right.right == null){
}
else if (node.left.left != null && node.left.right != null){
node.right = node.right.right;
node.right.left = node.right.right.left;
}
}
else {
deleteRecursive (key, node.right);
}
}
}
}
But when I actually use the delete method in Main its gives out a NullPointerException.
The error-message reads :
Exception in thread "main" java.lang.NullPointerException
at BinaryTree.deleteRecursive(BinaryTree.java:83)
at BinaryTree.delete(BinaryTree.java:58)
at Main.main(Main.java:14)
So I assume that it is in line 83 and 58 (marked in code).
I've been sitting here for the last hour trying to figure it out and can't seem to get it.
I'm not the best in Java so I thought i could look for some help here! :)
Here are all the files to run the program (everything except for the delete method was already given) : https://www.dropbox.com/sh/r1bt2880hnn6tjm/AADsRsOOzuiNKHp-ZC-IrvVta?dl=0
Since you are trying to remove from Binary Search Tree, better make it totally recursive rather than partially.
private BinaryNode deleteRecursive( int data,BinaryNode node) {
if(node==null){
return null;
}
if(data==node.value)
{
if(node.left!=null && node.right!=null){
BinaryNode minNode = getHighestNodeFromRight(node.right);
node.value = minNode.value;
node.right = deleteRecursive(minNode.value, node.right);
//System.out.println(minNode);
}
else if(node.left==null){
return node.right;
}
else{
return node.left;
}
}
else if(data>node.value){
node.right = deleteRecursive( data,node.right);
}
else{
node.left = deleteRecursive(data, node.left);
}
return node;
}
public BinaryNode getHighestNodeFromRight(BinaryNode node){
if(node.left==null){
return node;
}
else{
BinaryNode n = getHighestNodeFromRight(node.left);
return n;
}
}
I am basically completing a hacker rank excercise where you return 1 if the list is completely equal meaning there are same number of nodes in two lists and all the values in nodes also equal. Otherwise you return 0.
This is the method I wrote and for some reason I keep failing the test case i am not sure why. I wrote down some test cases in my book and did hand tracing and still can't seem to figure it out why.
int CompareLists(Node headA, Node headB) {
// This is a "method-only" submission.
// You only need to complete this method
Node temp = headA;
Node temp2 = headB;
int equal = 1;
if(temp == null && temp2 == null){
equal = 1;
}
else if((temp == null && temp2 != null) || (temp!=null && temp2 == null)){
equal = 0;
}
else{
while(temp.next != null){
if(temp.data != temp2.data || temp2.next == null){
equal = 0;
break;
}
temp = temp.next;
temp2 = temp2.next;
}
if(temp2.next != null){
equal = 0;
}
}
return equal;
}
Yes i found many solutions online but I am more curious as to why my solution is not working.
The code
while(temp.next != null){
if(temp.data != temp2.data || temp2.next == null){
equal = 0;
break;
}
temp = temp.next;
temp2 = temp2.next;
}
if(temp2.next != null){
equal = 0;
}
will never compare the last element of the first list with the corresponding element of the second list because your loop stops early. Try this instead:
while(temp != null){
if(temp2 == null || temp.data != temp2.data){
equal = 0;
break;
}
temp = temp.next;
temp2 = temp2.next;
}
if(temp2 != null){
equal = 0;
}
Using temp != null as loop condition makes sure, we also check the last element. The same adaption has been done for the check temp2.next == null, which is now temp2 == null. And this check has to be done before the comparison of data, in order to avoid a NullPointerException during the data comparison.
I personally would write that part more like this:
while(temp != null && temp2 != null){
if(temp.data.equals(temp2.data)){
return false;
}
temp = temp.next;
temp2 = temp2.next;
}
return temp == temp2;
I consider it easier to understand because it is symmetric. Usage of equals makes sure, we compare the actual content of the payload, not just references. I'd also use boolean as return type.
You can use recursive function.
public boolean isIdenticalRecursive(Node a, Node b) {
if (a == null && b == null) {
return true;
}
if (a.data != b.data)
return false;
return isIdenticalRecursive(a.next, b.next);
}
Hope this will help !! :)
This works:
int CompareLists(Node headA, Node headB) {
if ((headA == null)^(headB == null))
return false;
if ((headA == null) && (headB == null))
return true;
if (headA.data != headB.data)
return false;
return CompareLists(headA.next, headB.next);
}
And the cleanest way ever:
static boolean compareLists(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {
while(head1 != null && head2 != null && head1.data == head2.data) {
head1 = head1.next;
head2 = head2.next;
}
return head1 == head2;
}
public int compare_list(Node A, Node B) {
Node tail_A = A;
Node tail_B = B;
while(tail_A != null && tail_B != null){
if(tail_A.val != tail_B.val){
return 0;
}
tail_A = tail_A.next;
tail_B = tail_B.next;
}
if(tail_A == tail_B){
return 1; // if Equal lengths and same values
}
else{
return 0; // Only length are not equal
}
}
I am finding the 'next' node (i.e., in-order successor) of a given node in a binary search tree.
Why is this condition used in the code given below:
if (n.parent == null || n.right != null)
My question is: Why are we checking for n.parent == null ?
Full Code:
public static TreeNode inorderSucc(TreeNode n) {
if (n == null) return null;
// Found right children -> return left most node of right subtree
if (n.parent == null || n.right != null) {
return leftMostChild(n.right);
} else {
TreeNode q = n;
TreeNode x = q.parent;
// Go up until we’re on left instead of right
while (x != null && x.left != q) {
q = x;
x = x.parent;
}
return x;
}
}
public static TreeNode leftMostChild(TreeNode n) {
if (n == null) {
return null;
}
while (n.left != null) {
n = n.left;
}
return n;
}
if (n.parent == null || n.right != null)
Checking if n is the root node and it has a right subtree.
I need to create a recursive method that takes as a parameter the root node of a binary search tree. This recursive method will then return the int value of the total number of inner nodes in the entire binary search tree.
This is what I have so far:
int countNrOfInnerNodes (Node node) {
if(node == null) {
return 0;
}
if (node.left != null && node.right != null){
return 1;
}
return countNrOfInnerNodes(node.left)+countNrOfInnerNodes(node.right)
}
}
Is there a better way? I also stuck to find a iterativ solution.
Here's the recursive method fixed:
int countNrOfInnerNodes (Node node) {
if(node == null) {
return 0;
}
if (node.left == null && node.right == null) {
// not an inner node !
return 0;
} else {
// the number of inner nodes in the left sub-tree + the number of inner
// nodes in the right sub-tree, plus 1 for this inner node
return countNrOfInnerNodes(node.left) + countNrOfInnerNodes(node.right) + 1;
}
}
Here's the iterative method:
int countNrOfInnerNodes(Node node) {
if (node == null)
return 0;
Stack<Node> nodesToCheck = new Stack<Node>();
nodesToCheck.push(node);
int count = 0;
while (!nodesToCheck.isEmpty()) {
Node checkedNode = nodesToCheck.pop();
boolean isInnerNode = false;
if (node.left != null) {
isInnerNode = true;
nodesToCheck.push(node.left);
}
if (node.right != null) {
isInnerNode = true;
nodesToCheck.push(node.right);
}
if (isInnerNode)
count++;
}
return count;
}
I'm trying to remove all of the leaves. I know that leaves have no children, this is what I have so far.
public void removeLeaves(BinaryTree n){
if (n.left == null && n.right == null){
n = null;
}
if (n.left != null)
removeLeaves(n.left);
if (n.right != null)
removeLeaves(n.right);
}
n = null; won't help you, since n is just a local variable of your function. Instead, you'd need to set n.left = null; or n.right = null; on the parent.
I won't give you a complete solution, since this smells a lot like homework, but you could, for example, add a return value to your function to indicate whether the node in question is a leaf or not and take appropriate actions in the parent (after the call to removeLeaves).
It's much easier if you break this down like this:
public void removeLeaves(BinaryTree n){
if (n.left != null) {
if (n.left.isLeaf()) {
n.removeLeftChild();
} else {
removeLeaves(n.left);
}
}
// repeat for right child
// ...
}
isLeaf, removeLeftChild and removeRightChild should be trivial to implement.
Instead of n = null, it should be:
if(n.parent != null)
{
if(n.parent.left == n)
{
n.parent.left = null;
}
else if(n.parent.right == n)
{
n.parent.right == null);
}
}
Since Java passes references by values n = null; simply does not work. With this line n was pointing to the leaf and now points to nothing. So you aren't actually removing it from the parent, you are just rerouting a dummy local reference. For the solution do what Matthew suggested.
Here's a simple java method to delete leaf nodes from binary tree
public BinaryTreeNode removeLeafNode(BinaryTreeNode root) {
if (root == null)
return null;
else {
if (root.getLeft() == null && root.getRight() == null) { //if both left and right child are null
root = null; //delete it (by assigning null)
} else {
root.setLeft(removeLeafNode(root.getLeft())); //set new left node
root.setRight(removeLeafNode(root.getRight())); //set new right node
}
return root;
}
}
Easy method with recusrion .
public static Node removeLeaves(Node root){
if (root == null) {
return null;
}
if (root.left == null && root.right == null) {
return null;
}
root.left = removeLeaves(root.left);
root.right = removeLeaves(root.right);
return root;
}
/* #author abhineet*/
public class DeleteLeafNodes {
static class Node{
int data;
Node leftNode;
Node rightNode;
Node(int value){
this.data = value;
this.leftNode = null;
this.rightNode = null;
}
}
public static void main(String[] args) {
Node root = new Node(1);
Node lNode = new Node(2);
lNode.leftNode = new Node(4);
root.leftNode = lNode;
Node rNode = new Node(3);
rNode.rightNode = new Node(5);
root.rightNode = rNode;
printTree(root);
deleteAllLeafNodes(root, null,0);
System.out.println("After deleting leaf nodes::");
printTree(root);
}
public static void deleteAllLeafNodes(Node root, Node parent, int direction){
if(root != null && root.leftNode == null && root.rightNode == null){
if(direction == 0){
parent.leftNode = null;
}else{
parent.rightNode = null;
}
}
if(root != null && (root.leftNode != null || root.rightNode != null)){
deleteAllLeafNodes(root.leftNode, root, 0);
deleteAllLeafNodes(root.rightNode, root, 1);
}
}
public static void printTree(Node root){
if(root != null){
System.out.println(root.data);
printTree(root.leftNode);
printTree(root.rightNode);
}
}
}
This should work-
public boolean removeLeaves(Node n){
boolean isLeaf = false;
if (n.left == null && n.right == null){
return true;
//n = null;
}
if (n!=null && n.left != null){
isLeaf = removeLeaves(n.left);
if(isLeaf) n.left=null; //remove left leaf
}
if (n!=null && n.right != null){
isLeaf = removeLeaves(n.right);
if(b) n.right=null; //remove right leaf
}
return false;
}