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.
Related
This removes almost all of what is supposed to, except for the last item.
This is what I get back when I submit it:
Input: [thing, word, stuff, and, both, zoo, yes]
----------Expected size: 0 BST actual number of nodes: 1
Invalid tree after removing thing
Code Below:
#SuppressWarnings("unchecked")
public boolean remove(Object o) {
Node n = root;
while (n != null) {
int comp = n.value.compareTo(o);
if (comp == 0) {
size--;
remove(n);
return true;
} else if (comp > 0) {
n = n.left;
} else {
n = n.right;
}
}
return false;
}
private void remove(Node root) {
if (root.left == null && root.right == null) {
if (root.parent == null) {
root = null;
} else {
if (root.parent.left == root) {
root.parent.left = null;
} else {
root.parent.right = null;
}
}
} else if (root.left == null || root.right == null) {
Node child = root.left;
if (root.left == null) {
child = root.right;
}
if (root.parent == null) {
root = child;
} else if (root.parent.left == root) {
root.parent.left = child;
} else {
root.parent.right = child;
}
child.parent = root.parent;
} else {
Node successor = root.right;
if (successor.left == null) {
root.value = successor.value;
root.right = successor.right;
if (successor.right != null) {
successor.right.parent = root;
}
} else {
while (successor.left != null) {
successor = successor.left;
}
root.value = successor.value;
successor.parent.left = successor.right;
if (successor.right != null) {
successor.right.parent = successor.parent;
}
}
}
}
Removal of a node in a Binary-search-tree consists of the following steps:
Find the node
You need to make sure that you have a function which is used for searching in order to find the node to be removed.
Handle the node's subtree
If the node has less than two children, then the subtree can be trivially changed. If there is a child, then the current node will be replaced by its child. Otherwise, if there are two children of the node to be removed, then you will just need to replace the node to be removed with the rightmost node of the left subtree or the leftmost node of the right subtree of the element to be removed.
Ensure that if you have replaced your current node with something else, then the other node will not exist as a duplicate.
In order to achieve this you will need methods like:
- search
- find leftmost/rightmost node of subtree
- remove
Your current code is over-complicated. I would rewrite it using atomic methods.
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 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 :)
I've spent hours trying to figure it out. I've checked and the delete function does find the node, but when I try to delete it by setting it as null or equal to a child node it doesn't change the tree at all when I print it out for a second time. Can anyone help me figure out what I've done wrong or at least guide me to what I need to do to fix it?
class BST {
Node root;
void BST () {
root = new Node("B");
insert (root, "A");
insert (root, "D");
insert (root, "C");
inOrder (root);
System.out.println (" ");
delete (root, "D");
//root.LEFT = null;
inOrder (root);
}
void insert (Node n, String newKEY) {
if (n.KEY.compareTo(newKEY) > 0) {
if (n.LEFT == null) n.LEFT = new Node(newKEY);
else if (n.LEFT != null && n.LEFT.KEY.compareTo(newKEY) < 0) n.LEFT = new Node(n.LEFT, newKEY, null);
else insert (n.LEFT, newKEY);
}
if (n.KEY.compareTo(newKEY) < 0) {
if (n.RIGHT == null) n.RIGHT = new Node(newKEY);
else if (n.RIGHT != null && n.RIGHT.KEY.compareTo(newKEY) > 0) n.RIGHT = new Node(null, newKEY, n.RIGHT);
else insert (n.RIGHT, newKEY);
}
else if (n.KEY.compareTo(newKEY) == 0) n.C++;
}
void delete (Node n, String s) {
// Visit, check if proper node, if so then delete
if (n.KEY.compareTo(s) == 0) {
System.out.println (n.KEY);
// Deleting a node with no children
if (n.LEFT == null && n.RIGHT == null) n = null;
// Deleting a node with only left child
else if (n.RIGHT == null) n = n.LEFT;
// Deleting a node with only right child
else if (n.LEFT == null) n = n.RIGHT;
// Deleting a node with two children
else deleteNode_Two_Children (n, s);
}
// Left
else if (n.KEY.compareTo(s) > 0) delete (n.LEFT, s);
// Right
else if (n.KEY.compareTo(s) < 0) delete (n.RIGHT, s);
}
boolean find (Node n, String s) {
if (n.KEY.compareTo(s) > 0) {
if (n.LEFT == null) return false;
else if (n.LEFT != null && n.LEFT.KEY.compareTo(s) < 0) return false;
else find (n.LEFT, s);
}
if (n.KEY.compareTo(s) < 0) {
if (n.RIGHT == null) return false;
else if (n.RIGHT != null && n.RIGHT.KEY.compareTo(s) > 0) return false;
else find (n.RIGHT, s);
}
else if (n.KEY.compareTo(s) == 0) return true;
return false;
}
void deleteNode_Two_Children (Node n, String st) {
Node s = getSuccessor(n);
n = new Node (n.LEFT, s.KEY, s.C, n.RIGHT);
delete (s, st);
}
Node getSuccessor (Node n) {
Node temp = new Node();
while (n.LEFT != null) {
temp = n.LEFT;
n = temp;
}
return temp;
}
void inOrder (Node n) {
// Left
if (n.LEFT != null) inOrder (n.LEFT);
// Visit
System.out.print (n.KEY + " - " + n.C + ", ");
// Right
if (n.RIGHT != null) inOrder (n.RIGHT);
}
public static void main(String args[]){
BST t = new BST();
t.BST();
}
}
class Node {
String KEY;
int C;
Node LEFT;
Node RIGHT;
Node (String key) {
KEY = key;
C = 1;
LEFT = null;
RIGHT = null;
}
Node (Node L, String key, Node R) {
LEFT = L;
RIGHT = R;
KEY = key;
C = 1;
}
Node (Node L, String key, int c, Node R) {
LEFT = L;
RIGHT = R;
KEY = key;
C = c;
}
Node () {
KEY = null;
C = 0;
LEFT = null;
RIGHT = null;
}
// If 'this' is less than 'other', a negative number will be returned,
// 0 if equal
// Positive number if 'this' is greater.
int compare (Node other) {
return this.KEY.compareTo(other.KEY);
}
boolean equals (Node other) {
return this.KEY.equals(other.KEY);
}
}
The problem is your assumption that setting n to null will remove the node. Consider the following:
Object x = new Object();
public void someMethod(Object o) {
o = null;
}
This won't modify x. Java is pass-by-value, where o is the reference to some Object. You can certainly modify the internals of o through o's methods:
o.setValue(1);
This works because the value of o is really some address on the heap, which isn't being modifed. You can't overwrite o itself (eg, you can't set it to null or a new Object()). In order for you to delete a node, you must find the node's parent and set it's left or right child (whichever one you with to remove) and set that to null. Also, if that node has children, you have to make sure they aren't removed just because their parent is removed.
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;
}