Deleting Node from BST - java

I think I got most of the cases to work except for case 2 (deletion node has only one subtree). My test case is the tree below without the 1, 2, 3 and 4 nodes:
This program is telling me that 6 was deleted from the tree but when I try printing the tree, it still shows that 6 is in the tree.
public class RandomNode {
static int size;
public static class Node {
int data;
Node left;
Node right;
public Node(int data) {
this.data = data;
left = null;
right = null;
size++;
}
}
// delete node in right subtree
public Node delete(Node root, int data) {
// base case - if tree is empty
if (root == null)
return root;
// search for deletion node
else if (data < root.data)
root.left = delete(root.left, data);
else if (data > root.data) {
root.right = delete(root.right, data);
} else {
// case 1: deletion node has no subtrees
if (root.left == null && root.right == null) {
root = null;
size--;
System.out.println(data + " successfully deleted from tree (case1)");
// case 2: deletion node has only one subtree
} else if (root.left != null && root.right == null) {
root = root.left;
size--;
System.out.println(data + " successfully deleted from tree (case2a)");
} else if (root.left == null && root.right != null) {
root = root.left;
size--;
System.out.println(data + " successfully deleted from tree (case2b)");
// case 3: deletion node has two subtrees
// *find min value in right subtree
// *replace deletion node with min value
// *remove the min value from right subtree or else there'll be
// a duplicate
} else if (root.left != null && root.right != null) {
Node temp;
if (root.right.right == null && root.right.left == null)
temp = findMinNode(root.left);
else
temp = findMinNode(root.right);
System.out.println(root.data + " replaced with " + temp.data);
root.data = temp.data;
if (root.right.right == null || root.left.left == null)
root.left = delete(root.left, root.data);
else
root.right = delete(root.right, root.data);
size--;
System.out.println(temp.data + " succesfuly deleted from tree (case3)");
}
}
return root;
}
// find min value in tree
public Node findMinNode(Node root) {
while (root.left != null)
root = root.left;
System.out.println("min value: " + root.data);
return root;
}
public void preOrderTraversal(Node root) {
if (root == null)
return;
preOrderTraversal(root.left);
System.out.println(root.data);
preOrderTraversal(root.right);
}
public static void main(String[] args) {
RandomNode r = new RandomNode();
Node root = new Node(6);
//root.left = new Node(2);
root.right = new Node(9);
//root.left.left = new Node(1);
//root.left.right = new Node(5);
//root.left.right.left = new Node(4);
//root.left.right.left.left = new Node(3);
root.right.left = new Node(8);
root.right.right = new Node(13);
root.right.left.left = new Node(7);
root.right.right.left = new Node(11);
root.right.right.right = new Node(18);
r.delete(root, 6);
r.preOrderTraversal(root);
}
}

When you do root = root.left; and size --, you must also make root.left = null.
Here you are simply making root as root.left but are not making root.left as null.

It's rather hard for me to follow since I'd write it functionally.
However,
if (root.right.right == null || root.left.left == null)
root.left = delete(root.left, root.data);
else
root.right = delete(root.right, root.data);
Is probably wrong, since it should mirror your earlier findMinNode() calls, and thus should probably be
if(root.right.right == null && root.right.left == null)
root.left = delete(root.left, root.data);
There is more wrong when debugging it.
First off, java is pass by value, so if you're deleting the top node (root), your pointer should be updated too. Hence, the call should be root = r.delete(root, 6);
Second, there's another bug. Case 2a assigns root to root.left... which is null. It should be root.right.
Having made those changes, the output then becomes:
6 successfully deleted from tree (case2b)
7
8
9
11
13
18

Related

Does not remove last item in Boolean remove(object o) method

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.

Why does deleting the root node keep the left subtrees but not my right subtrees?

So I have created a delete function for my BST implementation. It works properly for cases of deleting leaf nodes, and subtrees with a right child, but no left child and vice versa.
However, deleting the root node is giving me problems. I am trying to replace the root with its successor, and then set new root's right child equal to the old root's right child.
Example:
50
/ \
/ \
42 63
/ \ /
/ \ 55
21 43
\ \
23 \
/ \ 47
/ \
44 48
If I were to delete node 50 in my program, 55 would be the new root, but then 63 would just disappear, but everything else works fine.
Am I relinking the nodes wrong?
(Starts at "Problem is Here" comment in code)
//How I display my tree
//inprder traversal
private void inOrder(Node curr){
if(curr != null){
//traverse left
inOrder(curr.leftChild);
System.out.print("\n" + curr + "->");
//traverse right
inOrder(curr.rightChild);
}
}
public boolean deleteContact(String key){
//Start at root node
Node currentNode = root;
Node parent = root;
boolean isLeftChld = true;
//loop over left and right subtrees
//finds node to be deleted
while(!key.equals(currentNode.key)){
parent = currentNode;
if(key.compareToIgnoreCase(currentNode.key) < 0){
isLeftChld = true;
currentNode = currentNode.leftChild;
}else{
isLeftChld = false;
currentNode = currentNode.rightChild;
}
//Node never found
if(currentNode == null){
return false;
}
}
//if the node doesnt have children
//go ahead and delete
if(currentNode.leftChild == null && currentNode.rightChild == null){
if(currentNode == root){
root = null;
//Handle case of juss deleting leafs
}else if(isLeftChld){//check if it was a left or right child
//delete it
parent.leftChild = null;
}else{
parent.rightChild = null;
}
//situation of no right child
//handling node dissapearing
} else if(currentNode.rightChild == null){
if(currentNode == root){
root = currentNode.leftChild;
}else if (isLeftChld){
parent.leftChild = currentNode.leftChild;
}else{
parent.rightChild = currentNode.leftChild;
}
//situation of no left child
}else if(currentNode.leftChild == null){
if(currentNode == root){
root = currentNode.rightChild;
}else if (isLeftChld){
parent.leftChild = currentNode.rightChild;
}else{
parent.rightChild = currentNode.leftChild;
}
**Problem is Here**
//situation of two children being involved
//figure out which node will replace which
} else {
//Node temp = currentNode.rightChild;
Node successor = minValue(currentNode.rightChild);
if(currentNode == root){
root = successor;
}else if(isLeftChld){
parent.leftChild = successor;
}else{
parent.rightChild = successor;
}
root.leftChild = currentNode.leftChild;
}
return true;
}
//Function to return min value for a root node
//Used for delete function - finds succesor
private Node minValue(Node root)
{
Node minv = root;
while (root.leftChild != null)
{
minv = root.leftChild;
root = root.leftChild;
}
return minv;
}
You need to assign the right child as well.
//Root is 50 [42, 63]
if(currentNode == root){
root = successor;
//Root is 55 [null, null]
}else if(isLeftChld){
parent.leftChild = successor;
}else{
parent.rightChild = successor;
}
//Root is 55 [42, null]
root.leftChild = currentNode.leftChild;
The following line is missing:
root.rightChild = currentNode.rightChild;

Something wrong with my Invert tree or BFS traverse?

I had already attached two tree to test, but the answer below is weird.
Input are two trees and to check if they are inverted version. So i wrote a invert function and a BFS traverse to store the tree node into a String, through comparing the two string to check if they are inverted version.
The first tree is
5
15
14
9
6
3
1
The second tree is:
5
15
14
9
6
3
1
5
14
15
3
6
9
1
No, not mirror imagines
Process finished with exit code 0
public class CheckMirrorTree{
public static void main(String[] args) {
// add the first tree
TreeNode root = new TreeNode(5);
root.left = new TreeNode(15);
root.right = new TreeNode(14);
TreeNode rightChild = root.right;
TreeNode leftChild = root.left;
rightChild.left = new TreeNode(3);
rightChild.left.right = new TreeNode(1);
leftChild.right = new TreeNode(6);
leftChild.left = new TreeNode(9);
System.out.println("The first tree is");
String root1 = traverse(root);
// add the second tree
System.out.println("The second tree is:");
TreeNode secondRoot = new TreeNode(5);
secondRoot.right = new TreeNode(15);
secondRoot.left = new TreeNode(14);
TreeNode secondRightChild = secondRoot.right;
TreeNode secondLeftChild = secondRoot.left;
secondRightChild.left = new TreeNode(6);
secondRightChild.right = new TreeNode(9);
secondLeftChild.right = new TreeNode(3);
secondLeftChild.right.left = new TreeNode(1);
String root2 = traverse(secondRoot);
if (root1 == root2){
System.out.println("Yes, mirror images");
}else {
System.out.println("No, not mirror imagines");
}
}
static Deque<TreeNode> queue = new ArrayDeque();
static List<Integer> result = new LinkedList();
static Deque<TreeNode> invertQueue = new ArrayDeque();
static private TreeNode invertTree(TreeNode root) {
invertQueue.add(root);
TreeNode reserve = root;
while (!invertQueue.isEmpty()) {
if (root.left != null || root.right != null) {
invertQueue.poll();
TreeNode temp = root.right;
root.right = root.left;
root.left = temp;
if (root.left != null)
invertQueue.add(root.left);
if (root.right != null)
invertQueue.add(root.right);
}
root = invertQueue.poll();
}
return reserve;
}
static private String traverse (TreeNode root){ // Each child of a tree is a root of its subtree.
queue.add(root);
helper(root);
// print out the tree
String res = "";
for (int i : result) {
System.out.println(i);
res += i;
}
return res;
}
static private void helper(TreeNode root) {
while (!queue.isEmpty()) {
if(root.left != null || root.right != null) {
TreeNode temp = queue.poll();
result.add(temp.val);
if (root.left != null)
queue.add(root.left);
if (root.right != null)
queue.add(root.right);
helper(queue.peek());
}
// deal with the ending nodes
if (root.left == null && root.right == null) {
if (queue.size() == 0) {
result.add(root.val);
return;
}
result.add(queue.poll().val);
root = queue.peek();
}
}
}
}
root1 == root2
is not how you check if two strings are equal. Try:
root1.equals(root2);
Then your if statement should be entered and something will be printed.
Since nothing else is getting printed I would suggest posting the traverse method since that's probably where the program is exiting early.

Binary Search Tree Node Removal not removing replacement Java

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!

Deleting Node in BST

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

Categories

Resources