I have BST and when I want to delete node from BST, nothing happened. Could someone explain why?
Here is my code:
private void delete(int value, Node node) {
if (value<node.value) delete(value, node.left);
else if (value> node.value)
delete(value, node.right);
else {
if (node.left != null && node.right != null) {
int maxFromLeft = findMax(node.left);
node.value = maxFromLeft;
delete(maxFromLeft, node.left);
} else if (node.left != null) {
Node trash = node;
node = node.left;
trash = null;
} else if (node.right != null) {
Node trash = node;
node = node.right;
trash = null;
} else {
node = null;
}
}
}
Consider this part
if (node.left != null) {
Node trash = node;
node = node.left;
trash = null;
}
You need to delete node. This do nothing node = node.left. It just assigns one reference to another. This dosn't need too trash = null.
To delete node you need to disconnect it from it's parent firstly, and connect a one child of a deleted node to the parent and insert other child where it should be!
A method with the signature void delete(int,Node) cannot work. Consider what happens when you try to delete the root from a tree that has only one node: this method cannot delete the node because method parameters are passed by value.
What you can do is return the modified BST from this method:
Node delete(int value, Node node) {
if (value<node.value) node.left = delete(value, node.left);
else if (value> node.value)
node.right = delete(value, node.right);
...I'll leave the rest as an exercise...
return node;
}
Related
I have implemented a simple binary tree program, but there is a problem I encounter while traversing the tree, only root element is accessed. I suspect the nodes aren't linked. I tried my best to figure out the problem but didn't find anything wrong with my code.
I tried printing the data from the insertion function, right before exiting the function, which did print the data correctly.
public class BinaryTree {
Node root;
public void addNode(int data){
Node newNode = new Node(data);
if(root == null){
root = newNode;
}
else{
Node currentNode = root;
while(true){
if(data <= currentNode.data){
currentNode = currentNode.leftChild;
if(currentNode == null){
currentNode = newNode;
return;
}
}
else{
currentNode = currentNode.rightChild;
if(currentNode == null){
currentNode = newNode;
return;
}
}
}
}
}
public void inorderTraversal(Node currentNode){
if(currentNode != null){
inorderTraversal(currentNode.leftChild);
System.out.print(currentNode.data + " ");
inorderTraversal(currentNode.rightChild);
}
}
}
In fact you are not adding the new node correctly to the tree during the recursive step. The logic you should be using is when you a reach a node whose left or right pointer be null, and the new node belongs in that direction, you should add the new node either to the left or right. Otherwise, keep traversing until you reach such node.
while(true) {
if (data <= currentNode.data) {
if (currentNode.leftChild == null) {
currentNode.leftChild = newNode;
return;
}
else {
currentNode = currentNode.leftChild;
}
else {
if (currentNode.rightChild == null) {
currentNode.rightChild = newNode;
return;
}
else {
currentNode = currentNode.rightChild;
}
}
}
Keep in mind that the above simple algorithm for adding new nodes is not guaranteed to necessarily result in a balanced binary tree. To ensure that, you would have to add more logic which handle rebalancing.
You are not assigning the element to the left or right child. You are just assigning it to the local variable currentNode - which is not linked to the tree.
Follow the below code to put inside the while loop & it should work for you.
if(data <= currentNode.data){
if(currentNode.leftChild == null){
currentNode.leftChild = newNode;
return;
}
else {
currentNode = currentNode.leftChild;
}
}
else{
if(currentNode.rightChild == null){
currentNode.rightChild = newNode;
return;
}
else {
currentNode = currentNode.rightChild;
}
}
I'm working on a binary search tree where i have to delete a node. The node has already been found, so i don't need to traverse and find the specific node. All i need is to delete a node, which is taken as an arguement.
I have started the the node remove method and currently only done how to delete a node if it has no children or is a leaf node. How do i implement a java code which will delete if it has 1 children or a parent?
my current remove method:
public void removeHelper(Node focus){
if(focus.leftChild == null && focus.rightChild == null){
focus = null;
}
// if the node has 1 child
// if the node has 2 children
}
You need to travel down the tree, because you will need to replace the root field, or either the leftChild or rightChild of the parent node.
To remove a node that has both leftChild and rightChild not null, you can replace the node with either the rightmost node of the left subtree, or the leftmost node of the right subtree.
In this example, I assume that the methods are in a class (Tree?) that have a Node field called root, and that the Nodes have a field value that is a Comparable:
public void remove(Node focus) {
root = removeHelper(root, focus);
}
public static Node removeHelper(Node root, Node focus) {
if (root == null) {
return null;
} else if (root == focus) {
if (focus.leftChild == null) {
return focus.rightChild;
} else if (focus.rightChild == null) {
return focus.leftChild;
} else {
Node node = removeLeftMostOfRight(focus);
node.leftChild = focus.leftChild;
node.rightChild = focus.rightChild;
return node;
}
} else {
int r = focus.value.compareTo(root.value);
if (r < 0) {
root.leftChild = removeHelper(root.leftChild, focus);
} else {
root.rightChild = removeHelper(root.rightChild, focus);
}
return root;
}
}
private static Node removeLeftMostOfRight(Node focus) {
Node node = focus.rightChild;
if (node.leftChild == null) {
focus.rightChild = node.rightChild;
} else {
Node prev;
do {
prev = node;
node = node.leftChild;
} while (node.leftChild != null);
prev.leftChild = node.rightChild;
}
return node;
}
Note that in languages like C/C++ you can have pointers to pointer, that allow a much simpler and more efficient implementation of binary trees.
I am trying to remove nodes from a Binary Search Tree. I can successfully remove any other node on the tree except for one particular case. If the targeted node has 2 children, and the left child has a right subtree, I can locate the correct replacement Node and switch the value to the targeted Node, but then the replacement node is never deleted.
Looking at the picture above, if I try to delete 17, the program will correctly navigate to 13 and replace 17 with 13, but it will not then delete the original 13 as it is supposed to.
I have attached my remove methods and those referenced within.
public Node root;
public void delete(int value){
Node node = new Node<>(value);
Node temp;
if(root == null) {
System.out.println("The tree is already empty!"); //tree is empty
return;
}
if (root.value == node.value) { //Root is target value
temp = node.left;
if(temp.right == null){
node.value = temp.value;
temp = null;
}
else{
while(temp.right != null){
temp = temp.right;
}
node.value = temp.value;
temp = null;
}
return;
}
deleteRec(root, node);
}
private void deleteRec(Node lastRoot, Node node){
Node temp;
if (lastRoot.value >= node.value){
if (lastRoot.left.value == node.value){
node = lastRoot.left;
if(node.left == null && node.right == null){ //No children
node = null;
lastRoot.left = null;
}
else if(node.left == null && node.right != null){ //Right Child
lastRoot.left = node.right;
node = null;
lastRoot.left = null;
}
else if(node.left != null && node.right == null){ //Left Child
lastRoot.left = node.left;
node = null;
}
else{ //Two Children
if(node.left.right == null){
node.value = node.left.value;
node.left = node.left.left;
node.left = null;
}
else{
node = findReplacement(node.left);
lastRoot.left.value = node.value;
node.left = null;
}
}
}
else{
deleteRec(lastRoot.left, node);
}
}
else{
if (lastRoot.right.value == node.value){
node = lastRoot.right;
if(node.left == null && node.right == null){ //No Children
node = null;
lastRoot.right = null;
}
else if(node.left == null && node.right != null){ //Right Child
lastRoot.left = node.right;
node = null;
lastRoot.right = null;
}
else if(node.left != null && node.right == null){ //Left Child
lastRoot.right = node.left;
node = null;
}
else{ //Two Children
if(node.left.right == null){
node.value = node.left.value;
node.left = node.left.left;
node.left = null;
}
else{
node = findReplacement(node.left);
lastRoot.left.value = node.value;
node.left = null;
}
}
}
else{
deleteRec(lastRoot.right, node);
}
}
}
private Node findReplacement(Node node) {
while(node.right != null){
node = node.right;
}
return node;
}
And here is my Node class:
public class Node<T> {
public int value;
public Node left;
public Node right;
public Node parent;
public Node(int value) {
this.value = value;
}
}
Consider this part of your code:
Node rep = findReplacement(node.left);
node.value = rep.value;
rep = null;
You're finding the replacement, and making rep point to it. Then, essentially what you're doing is making rep point to null. This doesn't remove the node! The parent is still pointing to it!
There are several places in your code where you're doing something along these lines. The way you're expected to remove nodes from a tree in this Java implementation is by changing what parents point to. The garbage collector takes care of the other details. I hope addressing this issue helps you resolve your problem!
I am working on a method to delete a node from a BST. In the same method, I recursively search for the node to be delete as well as saving the parent of that node. However, the only problem is that I am unsure how to make the root node equal the parent node (since the deletion happens in the parent node) in case2.
public Node delete(Node root, int data)
{
// base case - if tree is empty
if (root == null)
return root;
// find the node to be deleted and keep track of parent
if (data < root.data)
{
parent = root;
System.out.println("parent node: " + parent.data);
root.left = delete(root.left, data);
}
else if (data > root.data)
{
parent = root;
System.out.println("parent node: " + parent.data);
root.right = delete(root.right, data);
// delete node
}
else
{
// case 1: deletion node has no subtrees
if (root.left == null && root.right == null)
{
System.out.println(data + " successfully deleted from tree (case1)");
root = null;
}
// case 2: deletion node has only one subtree
else if (root.left != null && root.right == null)
{
Node temp = root.left;
if(parent.left.data == root.left.data)
{
parent.left = null;
System.out.println(data + " successfully deleted from tree (case2)");
parent.left = temp;
root = parent; // parent was sent when searching for the node
}
else if(parent.right.data == root.data)
{
parent.right = null;
System.out.println(data + " successfully deleted from tree (case2)");
parent.left = temp;
root = parent; // parent was sent when searching for the node
}
}
else if (root.left == null && root.right != null)
{
// same logic
}
}
return root;
}
You should add another function to call your delete function for that
class BST{
private Node root=null;
private Node parent=null;// just for use by the deletion function
public void delete(int data){
Node dummy_node=new Node(0);//can be initialized to anything.
dummy_node.setLeft(root); //right is null;
parent=dummy_node;
root=your_delete(this.root,data);
dymmy_node=null;
}
public Node your_delete(Node root, int data) {
//your code here
}
}
This will work, but thre's better way to do deletion. here:http://www.algolist.net/Data_structures/Binary_search_tree/Removal
I've been trying to create a integer binary search tree with Java and for some reason, I've been going wrong with adding new nodes to the tree.
Here is the NODE class.
class NODE
{
NODE left = null, right = null;
int info;
public NODE(int x)
{
info = x;
}
}
and here's the BST(Binary Seatch Tree) class with the insert() method.
class BST
{
NODE tree = null;
public void insert(int x)
{
NODE node = new NODE(x);
NODE temp = tree;
while(true)
{
if(temp == null)
{
temp = node;
break;
}
else if(temp.info > x) temp = temp.left;
else temp = temp.right;
}
}
//other methods present here
}
For reasons that I could not figure out, the insert() method is going wrong.
The object tree carries null in it even after the insert() method is called.
Can you find something spotty in the code?
Thanks!
Use a recursive insert method in the NODE class (instead of utilizing an infinite loop as you did):
public void insert(int x) {
if(x < this.info) {
if(this.left == null)
this.left = new NODE(x);
else
this.left.insert(x);
}
else {
if(this.right == null)
this.right = new NODE(x);
else
this.right.insert(x);
}
}
And your BST class would have the following insert method (simply calls the other insert method):
public void insert(int x) {
if(tree == null)
tree = new NODE(x);
else
tree.insert(x);
}
The main insert method is in the NODE class because it must recursively call itself on nodes within the tree.
Of course tree remains null - you don't assign anything to this field.
After temp = tree; and temp = node; only temp is changed, not tree.
The insert() method should insert the child of a node into the tree, calling an already declared Node as a parameter. e.g.:
//Returns true/false depending on whether the insert is successful
public boolean insert(int x, Node node, boolean leftChild) {
if (node == null) return false;
Node child = new Node(x);
if (leftChild) {
if (node.left != null) return false;
node.left = child;
} else {
if (node.right != null) return false;
node.right = child;
}
return true;
}