I'm working on a program that accepts a string which represents a prefix format binary expression (such as (A(B(C)(D))(E(F)(G))) ). I've been stuck on a part of the algorithm to add the data to nodes based on the parenthesis from separate stacks (after A for root, '('indicates a left node while ')' followed by '(' indicates a right. My code seems to run well enough until I hit the following code:
if (focus != null && val == '(') {
char nodeVal = tree.pop();
Node node = new Node(nodeVal);
focus = root;
while(focus != null) {
focus = focus.leftNode;
}
focus = node;
It passes through the "if (focus != null)", but when it hits the while loop, it either returns an error, doesn't add the new node or creates an infinite loop (based on a few variations I've been trying. The full code for the method is as follows if it helps:
public void constructTree(String input) {
for(int i = input.length()-1; i>=0; i--) {
if(input.charAt(i) == '(' || input.charAt(i) == ')') {
paren.push(input.charAt(i));
}
else {
tree.push(input.charAt(i));
}
}
while(!paren.isEmpty()) {
char val = paren.pop();
Node focus = root;
Node parent;
if (val == ')' && root == null) {
throw new InvalidTreeSyntax("Your tree cannot be empty");
}
if (root == null) {
char nodeVal = tree.pop();
Node node = new Node(nodeVal);
root = node;
}
if (focus != null && val == '(') {
char nodeVal = tree.pop();
Node node = new Node(nodeVal);
focus = root;
while(focus != null) {
focus = focus.leftNode;
}
focus = node;
}
else if (focus != null && val == ')' && paren.peek()== '(' || paren.peek() == null) {
char nodeVal = tree.pop();
Node node = new Node(nodeVal);
paren.pop();
while(focus!= null) {
focus = focus.rightNode;
}
focus = node;
}
}
}
I'm sure it's a simple mistake, but after a belly full of turkey and not enough sleep, I'm brain dead and need some help!
This is a recursive solution.
record Node(char value, Node left, Node right) {}
static Node constructTree(Deque<Integer> que) {
if (que.peek() != '(')
return null;
que.pop();
if (que.peek() == '(' || que.peek() == ')')
throw new RuntimeException("node value expected");
char nodeValue = (char)(int)que.pop();
Node left = constructTree(que);
Node right = constructTree(que);
if (que.peek() != ')')
throw new RuntimeException("')' expected");
que.pop();
return new Node(nodeValue, left, right);
}
static Node consturctTree(String s) {
return constructTree(s.chars().boxed()
.collect(Collectors.toCollection(ArrayDeque::new)));
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
String source = "(A(B(C)(D))(E(F)(G)))";
Node root2 = consturctTree(source);
System.out.println(root2);
}
output: (edited)
Node[value=A,
left=Node[value=B,
left=Node[value=C, left=null, right=null],
right=Node[value=D, left=null, right=null]],
right=Node[value=E,
left=Node[value=F, left=null, right=null],
right=Node[value=G, left=null, right=null]]]
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.
Heya I'm working on Binary tree and stuck on how to remove node from binary tree.I asked it from my instructor and did some googling but they wasn't helpful. My instructor said there is a 3 conditions to remove node from tree.
1.If node is leaf
2.If node has both child
3.If node has only one child
Here's code I wrote:
public void remove(Object theElement) {
BinaryTreeNode currentNode = this.root;
ArrayStack temp = new ArrayStack();
while(currentNode != null) {
if(currentNode.getLeftChild() == null
&& currentNode.getRightChild() == null
&& currentNode.getElement().equals(theElement)) {
currentNode = null;
break;
}
else if(currentNode.getLeftChild() != null
&& currentNode.getRightChild() == null
&& currentNode.getElement().equals(theElement)) {
BinaryTreeNode p = currentNode;
BinaryTreeNode c = currentNode.leftChild;
while(c != null) {
p = c;
c = c.rightChild;
}
p.rightChild = null;
System.out.println("Done removing node with left child");
break;
}
else if(currentNode.getLeftChild() == null
&& currentNode.getRightChild() != null
&& currentNode.getElement().equals(theElement)) {
BinaryTreeNode p = currentNode;
BinaryTreeNode c = currentNode.rightChild;
while(c != null) {
p = c;
c = c.rightChild;
}
p.rightChild = null;
System.out.println("Done removing node with right child");
break;
}
else if(currentNode.getLeftChild() != null
&& currentNode.getRightChild() != null
&& currentNode.getElement().equals(theElement)){
BinaryTreeNode p = currentNode;
BinaryTreeNode c = currentNode.rightChild;
while(c != null) {
p = c;
c = c.rightChild;
}
p.rightChild = null;
System.out.println("Done removing node with left and right child");
break;
}
else {
if(currentNode.getLeftChild() != null)
temp.push(currentNode.getLeftChild());
if(currentNode.getRightChild() != null)
temp.push(currentNode.getRightChild());
}
if(!temp.empty()) {
currentNode = (BinaryTreeNode)temp.pop();
}
else break;
}
}
I could find the node that is to be removed, but can't remove it. Please help :)
There are many ways to accomplish the above. Once way is to use recursion. Below is an example (not tested, just to demonstrate the concept).
package org.test.junk;
public class BTreeNode {
protected BTreeNode right;
protected BTreeNode left;
public void add(BTreeNode node, NodePosition nodePosition) {
switch(nodePosition) {
case left:{this.left=node;break;}
case right:{this.right=node;break;}
}//switch closing
}//add closing
public void remove(NodePosition nodePosition) {
switch(nodePosition) {
case left:{remove(left);break;}
case right:{remove(right);break;}
}//switch closing
}//remove closing
public void remove(BTreeNode node) {
if(node==null)return;
if(node.equals(right)) {
if(this.right!=null) {
this.right.remove(NodePosition.right);
this.right.remove(NodePosition.left);
this.right=null;
}//if closing
}//if closing
else if(node.equals(left)) {
if(this.left!=null) {
this.left.remove(NodePosition.right);
this.left.remove(NodePosition.left);
this.left=null;
}//if closing
}//else if closing
else return;
}//remove closing
public static enum NodePosition{
right,left;
}//enum closing
}//class closing
The idea is that if a parent node is called to remove its children (either left or right) will first call the child to remove all of its children recursively, conceptually.
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'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;
}