This is my first time running the debugger to check the values of my binary search tree but it seems to skip through all the debugger and it has a weird arrow beside the blue dot. By the way, the skip all breakpoints is disabled I made sure of it.
This is a short GIF of me running the program
https://gyazo.com/e236c1bd75ac746bf9982871ca847233
Added my other class
public class BinaryTree<T extends Comparable<T>> {
private class Node{
private T data;
private Node left;
private Node right;
// left and right child do not have to nessary exist
public Node ( T data) {
this.data = data;
this.left = null;
this.right = null;
}}
private Node root;
private int count = 0;
public void add( T data) {
if ( isEmpty()) {
root = new Node(data);
count++;
}
else {
insert(data, root);
count++;
}
}
public boolean isEmpty() {
return root == null;
}
public T getRoot() {
if ( root.data == null) {
System.out.println("Root is empty");
return null;
}
else {
return root.data;
}}
/*
* Checking if the data is larger or lesser than the parent's data
* If the data is smaller than the parent's data, node.left is created
* If the data is bigger than the parent's data, node.right is created
*/
private void insert( T data, Node node) {
/*
* If 1st obj is less than the 2nd obj return a neg
* if 1st obj is more than the 2nd obj return a pos
* if equal return 0
*/
int compare = data.compareTo(node.data);
if ( compare < 1 ){
if (node.left == null ) {
node.left = new Node(data);
}
// make node.left if it is filled
else {
insert(data, node.left);
}
}
else {
if ( node.right == null) {
node.right = new Node(data);
}
else {
insert( data, node.right);
}
}
}
public int getSize() {
return count;
}
private void removeInner( T data, Node node ) {
Node temp;
while ( node.data!=data) {
int compare = data.compareTo(node.data);
if ( compare < 1 ){
node = node.left;
}
// make node.left if it is filled
if ( compare > 1 ){
node = node.right;
}
if ( compare == 0) {
node = null;
}
}
}
}
You have one or more so-called Trigger Points (decorated with a T) somewhere else from which one must be hit first to activate the other regular breakpoints. This can be seen by the regular breakpoint in line 9 being decorated with a crossed-out T.
Solution: Delete or deactivate all Trigger Points (those decorated with T), e.g. in the Breakpoints view.
Related
The BST is as follows:
50 (Root 1)
/ \
40 80 (Root 2)
/ \
20 41
As you can see there are 2 root's that I am dealing with. I have tried the following code which does return the height of the tree from ROOT 1. I don't quite exactly know how to return the height from ROOT 2.
Any help on how to solve would be appreciated.
// Java program to find height of tree
// A binary tree node
class Node
{
int data;
Node left, right;
Node(int item)
{
data = item;
left = right = null;
}
}
class BinaryTree
{
Node root;
int maxDepth(Node node)
{
if (node == null)
return 0;
else
{
/* compute the depth of each subtree */
int lDepth = maxDepth(node.left);
int rDepth = maxDepth(node.right);
/* use the larger one */
if (lDepth > rDepth)
return (lDepth + 1);
else
return (rDepth + 1);
}
}
/* Driver program to test above functions */
public static void main(String[] args)
{
BinaryTree tree = new BinaryTree();
tree.root = new Node(1);
tree.root.left = new Node(2);
tree.root.right = new Node(3);
tree.root.left.left = new Node(4);
tree.root.left.right = new Node(5);
System.out.println("Height of tree is : " +
tree.maxDepth(tree.root));
}
Your function for finding max depth seems like to work correctly. So fixing this issue is pretty simple.
System.out.println("Height of tree is : " +
tree.maxDepth(tree.root));
The above line prints out the height of the tree starting at the root. But if you were to start at "root 2" as you call it you would need to modify this line to start at the correct node.
System.out.println("Height of tree is : " +
tree.maxDepth(tree.root.right));
Adding an item to a Tree class should be made through a insert method.
And we can make the Node class private, it is used only by BinaryTree class.
A better data structure for a tree should be like the following, which has public insert and height methods.
public class BinaryTree {
private class Node {
private int value;
private Node left;
private Node right;
private Node(int value) {
this.value = value;
}
}
private Node root;
public void insert(int item) {
var node = new Node(item);
if (root == null) {
root = node;
return;
}
var current = root;
while (true) {
if (item < current.value) {
if (current.left == null) {
current.left = node;
break;
}
current = current.left;
} else {
if (current.right == null) {
current.right = node;
break;
}
current = current.right;
}
}
}
public int height() {
return height(root);
}
private int height(Node root) {
if (root == null)
return -1;
if (isLeaf(root))
return 0;
return 1 + Math.max(height(root.left), height(root.right));
}
private boolean isLeaf(Node node) {
return node.left == null && node.right == null;
}
}
And to use it, just add some values, and print the height.
It is way easier to insert an item with this tree class.
BinaryTree tree = new BinaryTree();
tree.insert(50);
tree.insert(40);
tree.insert(80);
tree.insert(20);
tree.insert(41);
System.out.println(tree.height());
I have to find and return the next larger node in the generic tree almost all testcases are running fine and giving correct output just one testcase is coming out wrong and it could be anything. I have debugged my program many times and could not figured out what bug that could be? Actually what I'm doing I'm comparing all the next larger nodes that recursion has fetched for me and comparing them with one another and ultimately find the right one? I'm stuck a little help would be appreciated.
Code
/* TreeNode structure
class TreeNode<T> {
T data;
ArrayList<TreeNode<T>> children;
TreeNode(T data){
this.data = data;
children = new ArrayList<TreeNode<T>>();
}
}*/
public static TreeNode<Integer> findNextLargerNode(TreeNode<Integer> root, int n){
if(root==null)
return root;
if(root.children.size()==0)
{
if(root.data>n)
{
return root;
}
else
return null;
}
TreeNode<Integer> count[] = new TreeNode[root.children.size()];
for(int i=0;i<root.children.size();i++)
{
count[i] = findNextLargerNode(root.children.get(i),n);
}
int nextLarger=Integer.MAX_VALUE;
TreeNode<Integer> next = null;
for(int i=0;i<count.length;i++)
{
if(count[i]!=null)
{
if(count[i].data>n && count[i].data<nextLarger)
{
nextLarger = count[i].data;
next = count[i];
}
}
}
if(next!=null)
{
if(root.data>n && root.data<next.data)
return root;
else
return next;
}
else
return null;
}
I see one extreme test which could fail: if the correct answer is a node that has as data Integer.MAX_VALUE, then your code will return null instead of that node.
A solution with the least change to your code, is to replace:
count[i].data<nextLarger
with:
count[i].data<=nextLarger
This way you are sure to give next a non-null value even if count[i].data is Integer.MAX_VALUE.
NB: If you would join both for loops into one, you would not need to use a count array, but just a single node variable.
Finally, I have found the bug in my code. It lies in the following segment.
if(next!=null)
{
if(root.data>n && root.data<next.data)
return root;
else
return next;
}
else
return null;
Suppose if next == null then else will get executed which will return the null. This is wrong because root can also be the next larger node so I have to check for that condition also
The correct version is :
if(next!=null)
{
if(root.data>n && root.data<next.data)
return root;
else
return next;
}
else
{
if(root.data>n)
return root;
else
return null;
}
Try
public class Test {
class TreeNode<T> {
T data;
List<TreeNode<T>> children;
TreeNode(T data) {
this.data = data;
children = new ArrayList<TreeNode<T>>();
}
public TreeNode<T> findNextNode(T n,Comparator<T> comp) {
if (comp.compare(data , n) < 0) {
return this;
}
if (children.size() == 0) {
return null;
}
for (int i = 0; i < children.size(); i++) {
TreeNode<T> node= children.get(i).findNextNode(n,comp);
if(node!=null)return node;
}
return null;
}
}
Explanation:
Tests
To show some errors in your code I provide a test in testForYourCode (see below). The test returns an unexpected result. The second child with a value of 4 wins which is wrong.
In TreeNode<T>.findNextNode I provide a 'refactored' version. Not sure if it does what you have asked for. The two tests testForModifiedCodeand testForModifiedCodeComplex show how the refactored version behaves.
Generic
Instead of writing a function that can deal only with TreeNode<Integer> I decided to write a generic function that works on all kind of types.
Comparison
The actual comparison is delegated to a Comparator object. An instance of a Comparator must be passed to the findNextNode method. This can be done on-the-fly using Java 8 lambda syntax, e.g. (a,b)->{return b-a;}. This adds some flexibility to the implementation. By changing the comparator you can also search for the 'next lesser node' using (a,b)->{return a-b;}.
What it does
If the entry node fulfills the criteria defined by the Comparator.compare implementation the algorithm stops. Otherwise a deep search is performed starting at the first child node (and so forth). As soon as the node matches the comparison criteria the algorithm stops. If no node matches, null is returned.
package stack43210199;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.junit.Assert;
public class Test {
class TreeNode<T> {
T data;
List<TreeNode<T>> children;
TreeNode(T data) {
this.data = data;
children = new ArrayList<TreeNode<T>>();
}
public TreeNode<T> findNextNode(T n,Comparator<T> comp) {
if (comp.compare(data , n) < 0) {
return this;
}
if (children.size() == 0) {
return null;
}
for (int i = 0; i < children.size(); i++) {
TreeNode<T> node= children.get(i).findNextNode(n,comp);
if(node!=null)return node;
}
return null;
}
}
#org.junit.Test
public void testForYourCode() {
TreeNode<Integer> root = buildNode(0);
TreeNode<Integer> firstChild = buildNode(5);
TreeNode<Integer> secondChild = buildNode(4);
TreeNode<Integer> thirdChild = buildNode(5);
root.children.add(firstChild);
root.children.add(secondChild);
root.children.add(thirdChild);
//Arrg - not as expected
Assert.assertEquals(secondChild, findNextLargerNode(root, 0));
}
#org.junit.Test
public void testForModifiedCode() {
TreeNode<Integer> root = buildNode(2);
TreeNode<Integer> firstChild = buildNode(5);
TreeNode<Integer> secondChild = buildNode(4);
TreeNode<Integer> thirdChild = buildNode(5);
TreeNode<Integer> fourthChild = buildNode(1);
root.children.add(firstChild);
root.children.add(secondChild);
root.children.add(thirdChild);
thirdChild.children.add(fourthChild);
//find next greater
Assert.assertEquals(firstChild, root.findNextNode(2,(a,b)->{return b-a;}));
//find next lesser
Assert.assertEquals(fourthChild, root.findNextNode(2,(a,b)->{return a-b;}));
}
#org.junit.Test
public void testForModifiedCodeComplex() {
TreeNode<Integer> root = buildNode(2);
TreeNode<Integer> firstChild = buildNode(2);
TreeNode<Integer> secondChild = buildNode(4);
TreeNode<Integer> thirdChild = buildNode(5);
TreeNode<Integer> fourthChild = buildNode(1);
TreeNode<Integer> sixthChild = buildNode(8);
firstChild.children.add(fourthChild);
firstChild.children.add(sixthChild);
root.children.add(firstChild);
root.children.add(secondChild);
root.children.add(thirdChild);
//find next greater
Assert.assertEquals(sixthChild, root.findNextNode(2,(a,b)->{return b-a;}));
//find next lesser
Assert.assertEquals(fourthChild, root.findNextNode(2,(a,b)->{return a-b;}));
}
private TreeNode<Integer> buildNode(int i) {
return new TreeNode<Integer>(new Integer(i));
}
public static TreeNode<Integer> findNextLargerNode(TreeNode<Integer> root, int n) {
if (root == null)
return root;
if (root.children.size() == 0) {
if (root.data > n) {
return root;
}
else
return null;
}
TreeNode<Integer> count[] = new TreeNode[root.children.size()];
for (int i = 0; i < root.children.size(); i++) {
count[i] = findNextLargerNode(root.children.get(i), n);
}
int nextLarger = Integer.MAX_VALUE;
TreeNode<Integer> next = null;
for (int i = 0; i < count.length; i++) {
if (count[i] != null) {
if (count[i].data > n && count[i].data < nextLarger) {
nextLarger = count[i].data;
next = count[i];
}
}
}
if (next != null) {
if (root.data > n && root.data < next.data)
return root;
else
return next;
} else {
if (root.data > n)
return root;
else
return null;
}
}
}
A TreeNode would normally look like this.
class TreeNode<T extends Comparable<T>> {
T data;
TreeNode<T> left, right;
TreeNode(T data){
this.data = data;
}
public TreeNode<T> findNextLargerNode(T t) {
if (data.compareTo(t) <= 0)
return right == null ? null : right.findNextLargerNode(t);
T found = left == null ? null : left.findNextLargerNode(t);
return found == null ? this : found;
}
}
I was doing an assignment in which I'm supposed to create a binary tree and define given functions from its abstract superclass (AbstractBinaryTree.java).
While working on a function called getNumbers() which is basically going to traverse through the whole tree whilst adding values from each node to an array list which it returns. There seems to be a null pointer in one of my if statements.
AbstractBinaryTree.java
import java.util.ArrayList;
public abstract class AbstractBinaryTree
{
protected Node root;
protected int sizeOfTree;
public AbstractBinaryTree()
{
root = null;
sizeOfTree = 0;
}
public int size(){ return sizeOfTree; }
/** compute the depth of a node */
public abstract int depth(Node node);
/** Check if a number is in the tree or not */
public abstract boolean find(Integer i);
/** Create a list of all the numbers in the tree. */
/* If a number appears N times in the tree then this */
/* number should appear N times in the returned list */
public abstract ArrayList<Integer> getNumbers();
/** Adds a leaf to the tree with number specifed by input. */
public abstract void addLeaf(Integer i);
/** Removes "some" leaf from the tree. */
/* If the tree is empty should return null */
public abstract Node removeLeaf();
// these methods are only needed if you wish
// use the TreeGUI visualization program
public int getheight(Node n){
if( n == null) return 0;
return 1 + Math.max(
getheight(n.getLeft()) , getheight(n.getRight())
);
}
public int height(){ return getheight(root); }
}
Node.java File.
public class Node{
protected Integer data;
protected Node left;
protected Node right;
public Node(Integer data)
{
this.data = data;
this.left = this.right = null;
}
public Node(Integer data, Node left, Node right){
this.data = data;
this.left = left;
this.right = right;
}
public Integer getData(){ return this.data; }
public Node getLeft(){ return this.left; }
public Node getRight(){ return this.right; }
public void setLeft(Node left){ this.left = left; }
public void setRight(Node right){ this.right = right; }
public void setData(Integer data){ this.data = data; }
}
BinaryTree.java
import java.util.ArrayList;
import java.util.*;
// Student Name: Adrian Robertson
// Student Number: 101020295
//
// References: Collier, R. "Lectures Notes for COMP1406C- Introduction to Computer Science II" [PDF documents]. Retrieved from cuLearn: https://www.carleton.ca/culearn/(Winter2016).//
// References: http://codereview.stackexchange.com/questions/13255/deleting-a-node-from-a-binary-search-tree
// http://www.algolist.net/Data_structures/Binary_search_tree/Removal
// http://www.geeksforgeeks.org/inorder-tree-traversal- without-recursion-and-without-stack/
public class BinaryTree extends AbstractBinaryTree
{
protected Node root = new Node(12);
public static BinaryTree create()
{
BinaryTree tempTree = new BinaryTree();
//creating all the nodes
Node temp10 = new Node(10);
Node temp40 = new Node(40);
Node temp30 = new Node(30);
Node temp29 = new Node(29);
Node temp51 = new Node(51);
Node temp61 = new Node(61);
Node temp72 = new Node(72);
Node temp31 = new Node(31);
Node temp32 = new Node(32);
Node temp42 = new Node(42);
Node temp34 = new Node(34);
Node temp2 = new Node(2);
Node temp61x2 = new Node(61);
Node temp66 = new Node(66);
Node temp3 = new Node(3);
Node temp73 = new Node(73);
Node temp74 = new Node(74);
Node temp5 = new Node(5);
//setting up the tree
if (tempTree.root.getData() == null)
{
tempTree.root.setData(12);
tempTree.root.setLeft(temp10);
tempTree.root.setRight(temp40);
}
temp10.setLeft(temp30);
temp30.setRight(temp29);
temp29.setRight(temp51);
temp51.setLeft(temp61);
temp51.setRight(temp72);
temp40.setLeft(temp31);
temp31.setLeft(temp42);
temp31.setRight(temp34);
temp34.setLeft(temp61x2);
temp61x2.setLeft(temp66);
temp61x2.setRight(temp73);
temp40.setRight(temp32);
temp32.setRight(temp2);
temp2.setLeft(temp3);
temp3.setRight(temp74);
temp74.setLeft(temp5);
return tempTree;
}
public int depth(Node node)
{
Node current = this.root;
int counter = 1;
while(node != current)
{
if (node.getData() > current.getData())
current = current.getRight();
if (node.getData() < current.getData())
current = current.getLeft();
}
return counter;
}
public boolean find(Integer i)
{
boolean found = false;
Node current = this.root;
if (i == current.getData())
found = true;
while (i != current.getData())
{
if (i > current.getData())
current = current.getRight();
if (i < current.getData())
current = current.getLeft();
if (i == current.getData())
found = true;
}
return found;
}
public ArrayList<Integer> getNumbers()
{
ArrayList<Integer> temp = new ArrayList<Integer>();
Node current = this.root;
Node Pre = new Node(null);
while (current.getData() != null )
{
if (current.getLeft().getData() == null)
{
temp.add(current.getData());
current = current.getRight();
}
else
{
/* Find the inorder predecessor of current */
Pre = current.getLeft();
while(Pre.getRight() != null && Pre.getRight() != current)
Pre = Pre.getRight();
/* Make current as right child of its inorder predecessor */
if (Pre.getRight() == null)
{
Pre.setRight(current);
current = current.getLeft();
}
/* Revert the changes made in if part to restore the original tree i.e., fix the right child of predecssor */
else
{
Pre.setRight(null);
temp.add(current.getData());
current = current.getRight();
}/* End of if condition Pre.right == NULL */
}/* End of if condition current.left == NULL*/
}/*End of while */
Collections.sort(temp);
return temp;
}
public void addLeaf(Integer i)
{
insert(this.root, i);
}
public static void insert(Node node, int value) //insert a node Based on provided argument where node is the root of tree
{
if (node == null)
{
Node first = new Node(value);
node = first;
}
else if (value < node.getData())
{
if (node.left != null)
{
insert(node.left, value);
}
else
{
System.out.println(" > Inserted " + value + " to left of node " + node.getData());
Node newNode = new Node(value);
node.left = newNode;
}
}
else if (value > node.getData())
{
if (node.right != null)
{
insert(node.right, value);
}
else
{
System.out.println(" > Inserted " + value + " to right of node " + node.getData());
Node newNode = new Node(value);
node.right = newNode;
}
}
}
public Node removeLeaf()
{
Node tempA = new Node(61); //create a new node with that value
deleteNodeBST(this.root, 61); //delete the node containing that leaf value
return tempA; //return the copy of that node
}
//delete given node with given value
public boolean deleteNodeBST(Node node, int data) {
ArrayList<Integer> temp = this.getNumbers();
if (node == null) {
return false;
}
if (node.getData() == data) {
if ((node.getLeft() == null) && (node.getRight() == null)) {
// leaf node
node = null;
return true;
}
if ((node.getLeft() != null) && (node.getRight() != null)) {
// node with two children
node.setData(temp.get(0));
return true;
}
// either left child or right child
if (node.getLeft() != null) {
this.root.setLeft(node.getLeft());
node = null;
return true;
}
if (node.getRight() != null) {
this.root.setRight(node.getRight());
node = null;
return true;
}
}
this.root = node;
if (node.getData() > data) {
return deleteNodeBST(node.getLeft(), data);
} else {
return deleteNodeBST(node.getRight(), data);
}
}
public static void main(String args[])
{
BinaryTree myTree = new BinaryTree();
myTree.create();
System.out.println(myTree.getNumbers());
}
}
The create function creates a binary tree and returns that binary tree. This is the predefined binary tree that I was supposed to create according to assignment guidelines. I understand that the tree values are not organised properly as they would be in a proper binary tree. Is that was causes the null pointer during traversal? Cause the traversal is taylored to work for a proper Binary tree.
In class BinaryTree, you initialize the left and right of your root node only if the haven't data. But the root node is create with data...
You should invert the condition in :
//setting up the tree
if (tempTree.root.getData() == null)
And add a test in getNumbers() :
if (current.getLeft() == null || current.getLeft().getData() == null)
In the BinaryTree class, getNumbers() method and while loop. Maybe your problem is here:
if (current.getLeft().getData() == null) {
temp.add(current.getData());
current = current.getRight();
}
When you call current.getLeft(), it will return null when the left Node is null. And then, you call getData() it will throw a NullPointerException. If you're not sure that it always not null check it before you call any methods of it. Example you can change the if statement to:
if (current.getLeft() != null && current.getLeft().getData() == null) {
temp.add(current.getData());
current = current.getRight();
}
Or:
Node left = current.getLeft();
if (left == null) {
//TODO something here
} else if (left.getData() == null) {
temp.add(current.getData());
current = current.getRight();
}
Please update your getNumbers - method accordingly,
You need to put right checks before work with reference type.
public ArrayList<Integer> getNumbers()
{
ArrayList<Integer> temp = new ArrayList<Integer>();
Node current = this.root;
Node Pre = new Node(null);
while (current != null && current.getData() != null ) // Fix here... Add : current != null
{
if (current.getLeft() != null && current.getLeft().getData() == null) // Fix here... Add : current.getLeft() != null
{
temp.add(current.getData());
current = current.getRight();
}
else
{
/* Find the inorder predecessor of current */
Pre = current.getLeft();
while(Pre != null && Pre.getRight() != null && Pre.getRight() != current) // Fix here... Add : Pre != null
Pre = Pre.getRight();
/* Make current as right child of its inorder predecessor */
if (Pre != null && Pre.getRight() == null) // Fix here... Add : Pre != null
{
Pre.setRight(current);
current = current.getLeft();
}
/* Revert the changes made in if part to restore the original tree i.e., fix the right child of predecssor */
else
{
if(Pre != null){ // Fix here... Add : Pre != null
Pre.setRight(null);
}
temp.add(current.getData());
current = current.getRight();
}/* End of if condition Pre.right == NULL */
}/* End of if condition current.left == NULL*/
}/*End of while */
Collections.sort(temp);
return temp;
}
I am trying to implement a remove method for the BST structure that I have been working on. Here is the code with find, insert, and remove methods:
public class BST {
BSTNode root = new BSTNode("root");
public void insert(BSTNode root, String title){
if(root.title!=null){
if(title==root.title){
//return already in the catalog
}
else if(title.compareTo(root.title)<0){
if(root.leftChild==null){
root.leftChild = new BSTNode(title);
}
else{
insert(root.leftChild,title);
}
}
else if(title.compareTo(root.title)>0){
if(root.rightChild==null){
root.rightChild = new BSTNode(title);
}
else{
insert(root.rightChild,title);
}
}
}
}
public void find(BSTNode root, String title){
if(root!= null){
if(title==root.title){
//return(true);
}
else if(title.compareTo(root.title)<0){
find(root.leftChild, title);
}
else{
find(root.rightChild, title);
}
}
else{
//return false;
}
}
public void remove(BSTNode root, String title){
if(root==null){
return false;
}
if(title==root.title){
if(root.leftChild==null){
root = root.rightChild;
}
else if(root.rightChild==null){
root = root.leftChild;
}
else{
//code if 2 chlidren remove
}
}
else if(title.compareTo(root.title)<0){
remove(root.leftChild, title);
}
else{
remove(root.rightChild, title);
}
}
}
I was told that I could use the insert method to help me with the remove method, but I am just not seeing how I can grab the smallest/largest element, and then replace the one I am deleting with that value, then recursively delete the node that I took the replacement value, while still maintaining O(logn) complexity. Anyone have any ideas or blatant holes I missed, or anything else helpful as I bang my head about this issue?
EDIT:
I used the answers ideas to come up with this, which I believe will work but I'm getting an error that my methods (not just the remove) must return Strings, here is what the code looks like, I thought that's the return statements??
public String remove(BSTNode root, String title){
if(root==null){
return("empty root");
}
if(title==root.title){
if(root.leftChild==null){
if(root.rightChild==null){
root.title = null;
return(title+ "was removed");
}
else{
root = root.rightChild;
return(title+ "was removed");
}
}
else if(root.rightChild==null){
root = root.leftChild;
return(title+ "was removed");
}
else{
String minTitle = minTitle(root);
root.title = minTitle;
remove(root.leftChild,minTitle);
return(title+ "was removed");
}
}
else if(title.compareTo(root.title)<0){
remove(root.leftChild, title);
}
else{
remove(root.rightChild, title);
}
}
public void remove (String key, BSTNode pos)
{
if (pos == null) return;
if (key.compareTo(pos.key)<0)
remove (key, pos.leftChild);
else if (key.compareTo(pos.key)>0)
remove (key, pos.rightChild);
else {
if (pos.leftChild != null && pos.rightChild != null)
{
/* pos has two children */
BSTNode maxFromLeft = findMax (pos.leftChild); //need to make a findMax helper
//"Replacing " pos.key " with " maxFromLeft.key
pos.key = maxFromLeft.key;
remove (maxFromLeft.key, pos.leftChild);
}
else if(pos.leftChild != null) {
/* node pointed by pos has at most one child */
BSTNode trash = pos;
//"Promoting " pos.leftChild.key " to replace " pos.key
pos = pos.leftChild;
trash = null;
}
else if(pos.rightChild != null) {
/* node pointed by pos has at most one child */
BSTNode trash = pos;
/* "Promoting " pos.rightChild.key" to replace " pos.key */
pos = pos.rightChild;
trash = null;
}
else {
pos = null;
}
}
}
This is the remove for an unbalanced tree. I had the code in C++ so I have quickly translated. There may be some minor mistakes though. Does the tree you are coding have to be balanced? I also have the balanced remove if need be. I wasn't quite sure based on the wording of your question. Also make sure you add a private helper function for findMax()
void deleteTreeNode(int data){
root = deleteTreeNode(root ,data);
}
private TreeNode deleteTreeNode(TreeNode root, int data) {
TreeNode cur = root;
if(cur == null){
return cur;
}
if(cur.data > data){
cur.left = deleteTreeNode(cur.left, data);
}else if(cur.data < data){
cur.right = deleteTreeNode(cur.right, data);
}else{
if(cur.left == null && cur.right == null){
cur = null;
}else if(cur.right == null){
cur = cur.left;
}else if(cur.left == null){
cur = cur.right;
}else{
TreeNode temp = findMinFromRight(cur.right);
cur.data = temp.data;
cur.right = deleteTreeNode(cur.right, temp.data);
}
}
return cur;
}
private TreeNode findMinFromRight(TreeNode node) {
while(node.left != null){
node = node.left;
}
return node;
}
To compare objects in java use .equals() method instead of "==" operator
if(title==root.title)
^______see here
you need to use like this
if(title.equals(root.title))
or if you are interesed to ignore the case follow below code
if(title.equalsIgnoreCase(root.title))
private void deleteNode(Node temp, int n) {
if (temp == null)
return;
if (temp.number == n) {
if (temp.left == null || temp.right == null) {
Node current = temp.left == null ? temp.right : temp.left;
if (getParent(temp.number, root).left == temp)
getParent(temp.number, root).left = current;
else
getParent(temp.number, root).right = current;
} else {
Node successor = findMax(temp.left);
int data = successor.number;
deleteNode(temp.left, data);
temp.number = data;
}
} else if (temp.number > n) {
deleteNode(temp.left, n);
} else {
deleteNode(temp.right, n);
}
}
I know this is a very old question but anyways... The accepted answer's implementation is taken from c++, so the idea of pointers still exists which should be changed as there are no pointers in Java. So every time when you change the node to null or something else, that instance of the node is changed but not the original one This implementation is taken from one of the coursera course on algorithms.
public TreeNode deleteBSTNode(int value,TreeNode node)
{
if(node==null)
{
System.out.println("the value " + value + " is not found");
return null;
}
//delete
if(node.data>value) node.left = deleteBSTNode(value,node.left);
else if(node.data<value) node.right = deleteBSTNode(value,node.right);
else{
if(node.isLeaf())
return null;
if(node.right==null)
return node.left;
if(node.left==null)
return node.right;
TreeNode successor = findMax(node.left);
int data = successor.data;
deleteBSTNode(data, node.left);
node.data = data;
}
return node;
}
All the links between the nodes are pertained using the return value from the recursion.
For the Depth First Post-Order traversal and removal, use:
/*
*
* Remove uses
* depth-first Post-order traversal.
*
* The Depth First Post-order traversal follows:
* Left_Child -> Right-Child -> Node convention
*
* Partial Logic was implemented from this source:
* https://stackoverflow.com/questions/19870680/remove-method-binary-search-tree
* by: sanjay
*/
#SuppressWarnings("unchecked")
public BinarySearchTreeVertex<E> remove(BinarySearchTreeVertex<E> rootParameter, E eParameter) {
BinarySearchTreeVertex<E> deleteNode = rootParameter;
if ( deleteNode == null ) {
return deleteNode; }
if ( deleteNode.compareTo(eParameter) == 1 ) {
deleteNode.left_child = remove(deleteNode.left_child, eParameter); }
else if ( deleteNode.compareTo(eParameter) == -1 ) {
deleteNode.right_child = remove(deleteNode.right_child, eParameter); }
else {
if ( deleteNode.left_child == null && deleteNode.right_child == null ) {
deleteNode = null;
}
else if ( deleteNode.right_child == null ) {
deleteNode = deleteNode.left_child; }
else if ( deleteNode.left_child == null ) {
deleteNode = deleteNode.right_child; }
else {
BinarySearchTreeVertex<E> interNode = findMaxLeftBranch( deleteNode.left_child );
deleteNode.e = interNode.e;
deleteNode.left_child = remove(deleteNode.left_child, interNode.e);
}
} return deleteNode; } // End of remove(E e)
/*
* Checking right branch for the swap value
*/
#SuppressWarnings("rawtypes")
public BinarySearchTreeVertex findMaxLeftBranch( BinarySearchTreeVertex vertexParameter ) {
while (vertexParameter.right_child != null ) {
vertexParameter = vertexParameter.right_child; }
return vertexParameter; } // End of findMinRightBranch
I do have a hw question...I have to write a remove method for a binary search tree, so far what I have is below but I keep getting a bunch of errors associated with my remove method and I'm not sure why...would someone please be able to check my code. Thank You. I also tried to create a find method but I'm having some trouble with that as well...that is all the way at the bottom of my remove code.
import java.util.*;
class TreeNode383<E extends Comparable> {
private E data;
private TreeNode383<E> left;
private TreeNode383<E> right;
private TreeNode383<E> parent;
public TreeNode383( ) { left = right = parent = null; }
public TreeNode383( E d, TreeNode383 <E> l, TreeNode383 <E> r,
TreeNode383 <E> p) {
data = d;
left = l;
right = r;
parent = p;
}
public E getData( ) { return data; }
public void setData(E d) { data = d; }
public TreeNode383<E> getLeft( ) { return left; }
public void setLeft(TreeNode383<E> l) { left = l; }
public TreeNode383<E> getRight( ) { return right; }
public void setRight(TreeNode383<E> r) { right = r; }
public TreeNode383<E> getParent( ) { return parent; }
public void setParent(TreeNode383<E> p) { parent = p; }
public String toString( ) {
String answer = "";
if (left != null) answer += left.toString( );
answer += data + " ";
if (right != null) answer += right.toString( );
return answer;
}
}
**The start of my remove method**
boolean remove (E obj)
{
if(root == obj)
return false;
//when deleting a leaf just delete it
else if(obj.getleft == NULL && obj.getright == NULL)
parent = obj = NULL;
//when deleting an interior node with 1 child
//replace that node with the child
else if(obj.getleft == NULL && obj.getright != NULL)
obj.setright = new TreeNode383<E>(newData, null, null, null);
else if(obj.getleft != NULL && obj.getright == NULL
obj.setleft = new TreeNode383<E>(newData, null, null, null);
//when deleting an interior node with 2 children
//find left most node in right subtree,
//promote it to replace the deleted node
//promote its child to replace where it was
/*
private BinaryNode findMin( BinaryNode t )
{
if( t == null )
return null;
else if( t.left == null )
return t;
return findMin( t.left );
}
*/
obj is an instance of E not TreeNode383<E> so it has no getLeft() or getRight() method. And even if it did, you spelled it wrong.
And what's root? I can't see a declaration for that anywhere.
This syntax makes no sense either:
obj.setright = new TreeNode383<E>(newData, null, null, null);
setRight() is a method not a field (Java does not have properties like C#) Plus you need a capital 'R' in the name.
So maybe that should be
obj.setRight(new TreeNode383<E>(newData, null, null, null));
that is, if newData was declared, which it isn't.
There are too many errors here to make sense of your code. Try implementing one function at a time.
ya..there are some errors...basically, to remove a node N from a BST, replace N with the minimum element in the right subtree of N.