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
Related
so currently I’m trying to follow a tutorial from FreeCodeCamp on implementing a Binary tree, but I’m having trouble with adding to and traversing through my tree.
For some reason, it seems that I’m able to add nodes to my tree, but when I try to traverse through my tree via iterative preorder traversal, it only picks up my root node. Its as if my nodes aren’t pointing to each other.
I have a feeling that the problem either lies with my add method or my traversal method, both of which are below. Any help would be greatly appreciated.
Add method:
public boolean add(T thing)
{
if(contains(thing))
{
return false;
} else {
root = add(root,thing);
count++;
return true;
}
}
private Node add(Node node,T thing)
{
if(node == null)
{
node = new Node(thing,null,null);
} else
{
if(thing.compareTo(node.value) <0)
{
if(node.left == null)
{
node.left = node = new Node(thing,null,null);
} else{
node.left =add(node.left,thing);
}
}
else
{
if(node.right == null)
{
node.right = node = new Node(thing,null,null);
}else {
node.right = add(node.right,thing);
}
}
}
return node;
}
Traversal:
public void traverse()
{
preorder(root);
}
private void preorder(Node node)
{ int iteration=0;
java.util.Stack<Node> stack = new java.util.Stack<Node>();
System.out.println( "root is: " +node.value);
stack.push(node);
while(stack.empty() == false)
{
Node current = stack.pop();
System.out.println("in preorder: "+current.value);
if(current.right != null)
{
stack.push(current.right);
}
if(current.left != null)
{
stack.push(current.left);
}
iteration++;
}
System.out.println("iteration: "+iteration);
}
You are not traversing your tree while adding in the tree. Check my tree insert method to get the idea:-
void insert(Node temp,int value) {
if(temp==null){
temp=new Node(value,null,null);
this.root=temp;
}
else{
Queue<Node> q = new LinkedList<>();
q.add(temp);
while (!q.isEmpty()) {
temp = q.peek();
q.remove();
if (temp.left == null) {
temp.left = new Node(value, null, null);
break;
} else
q.add(temp.left);
if (temp.right == null) {
temp.right =new Node(value, null, null);
break;
} else
q.add(temp.right);
}
}
}
I have this method that uses recursion to find a node that holds a specified String in a binary tree. The issue is that it returns null, when it should return the node that holds the specified name, and I'm not sure why.
Here's the method:
public Node getNode(Node currentNode, String name) {
Node retrieved = null;
if (currentNode.getName().equals(name)) { retrieved = currentNode; }
else
{
if (currentNode.right != null) {
getNode(currentNode.right, name);
}
if (currentNode.left != null) {
getNode(currentNode.left, name);
}
}
return retrieved;
}
Any insight into what may be the problem would be appreciated.
You need to capture the return value of your two recursive calls. Otherwise you're doing recursion "for nothing" and throwing away the result of the recursion.
public Node getNode(Node currentNode, String name){
Node retrieved = null;
if (currentNode.getName().equals(name)) { retrieved = currentNode; }
else
{
if (currentNode.right != null){
retrieved = getNode(currentNode.right, name);
}
if (retrieved == null && currentNode.left != null){
retrieved = getNode(currentNode.left, name);
}
}
return retrieved;
}
The following solution is arguably better style because you leave null checks for a base case. Notice how you no longer need to check currentNode.right != null or currentNode.left != null, as they're covered by the base case after one more recursive step.
public static Node getNode(Node currentNode, String name){
// Base case: currentNode is null, nothing left to search
if (currentNode == null) {
return null;
}
Node retrieved = null;
if (currentNode.getName().equals(name)) {
retrieved = currentNode;
} else {
// Try to search right subtree
retrieved = getNode(currentNode.right, name);
// If not found in right subtree, then search left subtree
if (retrieved == null){
retrieved = getNode(currentNode.left, name);
}
}
return retrieved;
}
Solution
getNode(currentNode.right, name);
You call the getNode(...) method but you don't do anything with it.
A better solution
If you are willing to use googles Guava (must-have for every project in my opinion) and java 8, you can do the following:
public static final Traverser<Node> TREE_TRAVERSER =
Traverser.forTree((SuccessorsFunction<Node>) node ->
Stream.of(node.right, node.left)
.filter(Objects::nonNull)
.collect(Collectors.toList()));
And then call it where ever you want to traverse the tree:
for (Node n : TREE_TRAVERSER.depthFirstPreOrder(root)) {
if (n.getName().equals("foo")) {
// todo: do stuff with node foo
}
}
The java 8 way of traversing the tree would then be:
Iterable<Node> nodes = TREE_TRAVERSER.depthFirstPreOrder(root);
Optional<Node> result = StreamSupport.stream(nodes.spliterator(), false)
.filter(n -> n.getName().equals("foo")) // find node with name "foo"
.findAny(); // we assume there is <= 1 node, so we take any.
// node.isPresent() to check if you found a Node and result.get() to get the Node
How does this work?
Well, Guava has this nice class called a Traverser<N>. You just give it one parameter, which is the SuccessorsFunction<N>. It takes any object N and returns a Iterable<? extends N>, which are the child nodes.
We use Streams to do this. First we create a Stream of the two child nodes. We then filter them to only have a Stream of nonNull Nodes and collect them in a List (since the SuccessorsFunction<Node> wants to return a Iterable<Node>).
This Traverser<N> only has to be created once, so we made it public static final. You can now choose an iteration order. We chose depthFirstPreOrder, which returns an Iterable<N> we can iterate over
If you haven't heard of Streams before, I would recommend this turorial.
I would suggest taking tail recursions into account, since performance-wise this is a major factor :
public static Node getNode(Node currentNode, String name){
// Base case: currentNode is null, nothing left to search
if (currentNode == null) {
return null;
}
Node retrieved = null;
if (currentNode.name.equals(name)) {
return currentNode;
} else {
// Tail recursions
if(currentNode.left == null) {
return getNode(currentNode.right, name);
}
else if(currentNode.right == null) {
return getNode(currentNode.left, name);
}
// Non Tail recursion
else {
retrieved = getNode(currentNode.left, name);
// If not found in left subtree, then search right subtree
if (retrieved == null){
retrieved = getNode(currentNode.right, name);
}
}
}
return retrieved;
}
Attached is the full code which was executed on an online compiler:
public class MyClass {
static class Node {
public String name;
public Node left;
public Node right;
Node(String name) {
this.name = name;
right = null;
left = null;
}
#Override
public String toString() {
return "name = " + name + " hasLeft = " + (left != null) + " hasRight = " + (right != null);
}
}
static class Tree {
Node root;
public Node getRoot() {
return root;
}
private Node addRecursive(Node current, String value) {
if (current == null) {
return new Node(value);
}
if (value.compareTo(current.name) < 0) {
current.left = addRecursive(current.left, value);
} else if (value.compareTo(current.name) > 0) {
current.right = addRecursive(current.right, value);
} else {
// value already exists
return current;
}
return current;
}
public Tree add(String value) {
root = addRecursive(root, value);
return this;
}
public void traverseInOrder(Node node) {
if (node != null) {
traverseInOrder(node.left);
System.out.print(" " + node.name);
traverseInOrder(node.right);
}
}
public void traverseInOrder() {
traverseInOrder(root);
System.out.println("");
}
}
public static void main(String args[]) {
Tree tree = new Tree();
tree.add("a").add("ab").add("bbb").add("cc").add("zolko").add("polip").traverseInOrder();
Node found = getNode(tree.getRoot(),"vv");
System.out.println(found);
found = getNode(tree.getRoot(),"ab");
System.out.println(found);
found = getNode(tree.getRoot(),"polip");
System.out.println(found);
found = getNode(tree.getRoot(),"java");
System.out.println(found);
found = getNode(tree.getRoot(),"zolko");
System.out.println(found);
}
public static Node getNode(Node currentNode, String name){
// Base case: currentNode is null, nothing left to search
if (currentNode == null) {
return null;
}
Node retrieved = null;
if (currentNode.name.equals(name)) {
return currentNode;
} else {
// Tail recursions
if(currentNode.left == null) {
return getNode(currentNode.right, name);
}
else if(currentNode.right == null) {
return getNode(currentNode.left, name);
}
// Non Tail recursion
else {
retrieved = getNode(currentNode.left, name);
// If not found in left subtree, then search right subtree
if (retrieved == null){
retrieved = getNode(currentNode.right, name);
}
}
}
return retrieved;
}
}
And the outputs of the main method execution:
a ab bbb cc polip zolko
null
name = ab hasLeft = false hasRight = true
name = polip hasLeft = false hasRight = false
null
name = zolko hasLeft = true hasRight = false
Iterator words = treeSearch.getItems().iterator();
int addCount = 0;
while (words.hasNext())
{
numWords++;
rootNode = add(objectToReference, addCount++, (ITreeSearch) words.next(), 0, rootNode);
}
//Add to the Tree
private TernaryTreeNode add(Object storedObject, int wordNum, ITreeSearch treeSearch, int pos, TernaryTreeNode parentNode) throws NoSearchValueSetException
{
if (parentNode == null)
{
parentNode = new TernaryTreeNode(treeSearch.getNodeValue(pos));
}
if (parentNode.lessThan(treeSearch, pos))
{
parentNode.left = add(storedObject, wordNum, treeSearch, pos, parentNode.left);
}
else if (parentNode.greaterThan(treeSearch, pos))
{
parentNode.right = add(storedObject, wordNum, treeSearch, pos, parentNode.right);
}
else
{
if (pos < treeSearch.getNumberNodeValues())
{
parentNode.mid = add(storedObject, wordNum, treeSearch, pos + 1, parentNode.mid);
}
else
{
numberOfObjectsStored++;
parentNode.addStoredData(storedObject);
}
}
return parentNode;
}
This a snippet of my code in my Ternary Tree which I use for inserting a Name of a person(can hav multiple words in a name, like Michele Adams, Tina Joseph George, etc). I want to convert the above recursion to a for loop / while iterator.
Please guide me on this.
General idea in replacing recursion with iteration is to create a state variable, and update it in the loop by following the same rules that you follow in your recursive program. This means that when you pick a left subtree in the recursive program, you update the state to reference the left subtree; when you go to the right subtree, the state changes to reference the right subtree, and so on.
Here is an example of how to rewrite the classic insertion into binary tree without recursion:
public TreeNode add(TreeNode node, int value) {
// Prepare the node that we will eventually insert
TreeNode insert = new TreeNode();
insert.data = value;
// If the parent is null, insert becomes the new parent
if (node == null) {
return insert;
}
// Use current to traverse the tree to the point of insertion
TreeNode current = node;
// Here, current represents the state
while (true) {
// The conditional below will move the state to the left node
// or to the right node, depending on the current state
if (value < current.data) {
if (current.left == null) {
current.left = insert;
break;
} else {
current = current.left;
}
} else {
if (current.right == null) {
current.right = insert;
break;
} else {
current = current.right;
}
}
}
// This is the original node, not the current state
return node;
}
Demo.
Thanks dasblinkenlight..
This is my logic for replacing the above recursive function for a ternary tree.
Iterator words = treeSearch.getItems().iterator();
while (words.hasNext())
{
for (int i = 0; i < word.getNumberNodeValues(); i++)
{
add_Non_Recursive(objectToReference, word, i);
}
}
//Add to Tree
private void add_Non_Recursive(Object storedObject, ITreeSearch treeSearch, int pos) throws NoSearchValueSetException
{
TernaryTreeNode currentNode = rootNode;
// Start from a node(parentNode). If there is no node, then we create a new node to insert into the tree.
// This could even be the root node.
if (rootNode == null)
{
rootNode = new TernaryTreeNode(treeSearch.getNodeValue(pos));
}
else
{
while (currentNode != null)
{
if (currentNode.lessThan(treeSearch, pos))
{
if (currentNode.left == null)
{
currentNode.left = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.left;
}
}
else if (currentNode.greaterThan(treeSearch, pos))
{
if (currentNode.right == null)
{
currentNode.right = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.right;
}
}
else
{
if (currentNode.mid == null)
{
currentNode.mid = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.mid;
}
}
}
}
}
But I dropped this logic as it wasnt great in performing, it took more time than the recursive counterpart.
I am implementing a Red Black Tree with insert, search and delete functions in O (log n) time. Insert and search are working fine. However I am stuck on delete. I found this ppt slide on the internet which shows the algorithm of RBT deletion: http://www.slideshare.net/piotrszymanski/red-black-trees#btnNext on page 56 onwards. I know I am asking a bit too much but I have been stuck on this for over 2 weeks and I can't find the problem. The way I'm understanding Top-Down deletion that you have to rotate and recolor nodes accordingly until you find the predecessor of the node to be deleted. When you do find this node - which would be either a leaf or a node with one right child, replace node to be deleted data by the data of this node and delete this node like normal BST deletion, right?
This is the code I did, based on what I learnt from that slide. If anyone would be so kind to go over it, I would be more than grateful! Or at least if you think there's a better algorithm than what I'm using, please tell me!
public void delete(int element){
if (root == null){
System.out.println("Red Black Tree is Empty!");
} else {
Node X = root;
parent = null;
grandParent = null;
sibling = null;
if (isLeaf(X)){
if (X.getElement() == element){
emptyRBT();
}
} else {
if (checkIfBlack(root.getLeftChild()) && checkIfBlack(root.getRightChild())){
root.setIsBlack(false);
if (X.getElement() > element && X.getLeftChild() != null){
X = moveLeft(X);
} else if (X.getElement() < element && X.getRightChild() != null){
X = moveRight(X);
}
Step2(X, element);
} else {
Step2B(X, element);
}
}
}
root.setIsBlack(true);
}
public void Step2(Node X, int element)
{
int dir = -1;
while (!isLeaf(X)){
if (predecessor == null){ // still didn't find Node to delete
if (X.getElement() > element && X.getLeftChild() != null){
X = moveLeft(X);
dir = 0;
} else if (X.getElement() < element && X.getRightChild() != null){
X = moveRight(X);
dir = 1;
} else if (X.getElement() == element){
toDelete = X;
predecessor = inorderPredecessor(X.getRightChild());
X = moveRight(X);
}
} else { // if node to delete is already found and X is equal to right node of to delete
// move always to the left until you find predecessor
if (X != predecessor){
X = moveLeft(X);
dir = 0;
}
}
if (!isLeaf(X)){
if (!hasOneNullNode(X)){
if (checkIfBlack(X.getLeftChild()) && checkIfBlack(X.getRightChild())){
Step2A(X, element, dir);
} else {
Step2B(X, element);
}
}
}
}
removeNode(X);
if (predecessor != null){
toDelete.setElement(X.getElement());
}
}
public Node Step2A(Node X, int element, int dir) {
if (checkIfBlack(sibling.getLeftChild()) && checkIfBlack(sibling.getRightChild())) {
X = Step2A1(X);
} else if ((checkIfBlack(sibling.getLeftChild()) == false) && checkIfBlack(sibling.getRightChild())) {
X = Step2A2(X);
} else if ((checkIfBlack(sibling.getLeftChild()) && (checkIfBlack(sibling.getRightChild()) == false))) {
X = Step2A3(X);
} else if ((checkIfBlack(sibling.getLeftChild()) == false) && (checkIfBlack(sibling.getRightChild()) == false)) {
X = Step2A3(X);
}
return X;
}
public Node Step2A1(Node X) {
X.setIsBlack(!X.IsBlack());
parent.setIsBlack(!parent.IsBlack());
sibling.setIsBlack(!sibling.IsBlack());
return X;
}
public Node Step2A2(Node X) {
if (parent.getLeftChild() == sibling){
LeftRightRotation(sibling.getLeftChild(), sibling, parent);
} else RightLeftRotation(sibling.getRightChild(), sibling, parent);
X.setIsBlack(!X.IsBlack());
parent.setIsBlack(!parent.IsBlack());
return X;
}
public Node Step2A3(Node X) {
if (parent.getLeftChild() == sibling){
leftRotate(sibling);
} else if (parent.getRightChild() == sibling){
rightRotate(sibling);
}
X.setIsBlack(!X.IsBlack());
parent.setIsBlack(!parent.IsBlack());
sibling.setIsBlack(!sibling.IsBlack());
sibling.getRightChild().setIsBlack(!sibling.getRightChild().IsBlack());
return X;
}
public void Step2B(Node X, int element){
if (predecessor == null){
if (X.getElement() > element && X.getLeftChild() != null){
X = moveLeft(X);
} else if (X.getElement() < element && X.getRightChild() != null){
X = moveRight(X);
} else if (X.getElement() == element){
Step2(X, element);
}
} else {
if (X != predecessor)
X = moveLeft(X);
else Step2(X, element);
}
if (X.IsBlack()){
if (parent.getLeftChild() == sibling){
leftRotate(sibling);
} else if (parent.getRightChild() == sibling){
rightRotate(sibling);
}
parent.setIsBlack(!parent.IsBlack());
sibling.setIsBlack(!sibling.IsBlack());
Step2(X, element);
} else {
Step2B(X, element);
}
}
public void removeNode(Node X) {
if (isLeaf(X)) {
adjustParentPointer(null, X);
count--;
} else if (X.getLeftChild() != null && X.getRightChild() == null) {
adjustParentPointer(X.getLeftChild(), X);
count--;
} else if (X.getRightChild() != null && X.getLeftChild() == null) {
adjustParentPointer(X.getRightChild(), X);
count--;
}
}
public Node inorderPredecessor(Node node){
while (node.getLeftChild() != null){
node = node.getLeftChild();
}
return node;
}
public void adjustParentPointer(Node node, Node current) {
if (parent != null) {
if (parent.getElement() < current.getElement()) {
parent.setRightChild(node);
} else if (parent.getElement() > current.getElement()) {
parent.setLeftChild(node);
}
} else {
root = node;
}
}
public boolean checkIfBlack(Node n){
if (n == null || n.IsBlack() == true){
return true;
} else return false;
}
public Node leftRotate(Node n)
{
parent.setLeftChild(n.getRightChild());
n.setRightChild(parent);
Node gp = grandParent;
if (gp != null){
if (gp.getElement() > n.getElement()){
gp.setLeftChild(n);
} else if (gp.getElement() < n.getElement()){
gp.setRightChild(n);
}
} else root = n;
return n;
}
public Node rightRotate(Node n)
{
parent.setRightChild(n.getLeftChild());
n.setLeftChild(parent);
Node gp = grandParent;
if (gp != null){
if (gp.getElement() > n.getElement()){
gp.setLeftChild(n);
} else if (gp.getElement() < n.getElement()){
gp.setRightChild(n);
}
} else root = n;
return n;
}
The node is being deleted, but the tree after deletion would be black violated, which is very wrong.
The eternally confuzzled blog has top-down implementations of both insert and delete for red-black trees. It also goes through case-by-case why it works. I won't replicate it here (it's rather lengthy).
I've used that blog as a reference for implementing red-black trees in both c++ and java. As I discussed in an earlier answer, I found the implementation to be faster than std::map's bottom-up implementation of red-black trees (whatever STL came with gcc at the time).
Here's an untested, direct translation of the code to Java. I would highly suggest you test it and morph it to match your style.
private final static int LEFT = 0;
private final static int RIGHT = 1;
private static class Node {
private Node left,right;
private boolean red;
...
// any non-zero argument returns right
Node link(int direction) {
return (direction == LEFT) ? this.left : this.right;
}
// any non-zero argument sets right
Node setLink(int direction, Node n) {
if (direction == LEFT) this.left = n;
else this.right = n;
return n;
}
}
boolean remove(int data) {
if ( this.root != null ) {
final Node head = new Node(-1, null, null); /* False tree root */
Node cur, parent, grandpa; /* Helpers */
Node found = null; /* Found item */
int dir = RIGHT;
/* Set up helpers */
cur = head;
grandpa = parent = null;
cur.setLink(RIGHT, this.root);
/* Search and push a red down */
while ( cur.link(dir) != null ) {
int last = dir;
/* Update helpers */
grandpa = parent, parent = cur;
cur = cur.link(dir);
dir = cur.data < data ? RIGHT : LEFT;
/* Save found node */
if ( cur.data == data )
found = cur;
/* Push the red node down */
if ( !is_red(cur) && !is_red(cur.link(dir)) ) {
if ( is_red(cur.link(~dir)) )
parent = parent.setLink(last, singleRotate(cur, dir));
else if ( !is_red(cur.link(~dir)) ) {
Node s = parent.link(~last);
if ( s != null ) {
if (!is_red(s.link(~last)) && !is_red(s.link(last))) {
/* Color flip */
parent.red = false;
s.red = true;
cur.red = true;
}
else {
int dir2 = grandpa.link(RIGHT) == parent ? RIGHT : LEFT;
if ( is_red(s.link(last)) )
grandpa.setLink(dir2, doubleRotate(parent, last));
else if ( is_red(s.link(~last)) )
grandpa.setLink(dir2, singleRotate(parent, last));
/* Ensure correct coloring */
cur.red = grandpa.link(dir2).red = true;
grandpa.link(dir2).link(LEFT).red = false;
grandpa.link(dir2).link(RIGHT).red = false;
}
}
}
}
}
/* Replace and remove if found */
if ( found != null ) {
found.data = cur.data;
parent.setLink(
parent.link(RIGHT) == cur ? RIGHT : LEFT,
cur.link(cur.link(LEFT) == null ? RIGHT : LEFT));
}
/* Update root and make it black */
this.root = head.link(RIGHT);
if ( this.root != null )
this.root.red = false;
}
return true;
}
quick link :
http://algs4.cs.princeton.edu/33balanced/RedBlackBST.java.html
--> Caution : the code on the site is relying on two jars. In the datastructures however the dependency might be minimal. Sometimes it's enough to comment out the main method (that only serves as a test client)
If not : the jars are downloadable on the same site.
If you are looking for two weeks and studying algoritms, chances are you know about
http://algs4.cs.princeton.edu/
the website that is accompanying the famous
Algorithms, by Robert Sedgewick and Kevin Wayne
book.
On this website, there is this implementation of a red black (balances) tree :
http://algs4.cs.princeton.edu/33balanced/RedBlackBST.java.html
I didnot look into it yet (I will later on this year) , but I fully trust it to be a working implementation of a RBTree.
Some sidenote that might be interesting for visitors of this topic:
MIT placed excellent courses concerning algoritms online. The one concerning rbtrees is
http://www.youtube.com/watch?v=iumaOUqoSCk
I am trying to implement BST algorithm using Cormen's pseudo code yet having issue.
Here is my Code for Node:
public class Node {
Node left;
Node right;
int value;
Node(int value){
this.value = value;
this.left = null;
this.right = null;
}
}
and for the Bstree:
public class Btree {
Node root;
Btree(){
this.root = null;
}
public static void inorderWalk(Node n){
if(n != null){
inorderWalk(n.left);
System.out.print(n.value + " ");
inorderWalk(n.right);
}
}
public static Node getParent(Btree t, Node n){
Node current = t.root;
Node parent = null;
while(true){
if (current == null)
return null;
if( current.value == n.value ){
break;
}
if (current.value > n.value){
parent = current;
current = current.left;
}
else{ //(current.value < n.value)
parent = current;
current = current.right;
}
}
return parent;
}
public static Node search(Node n,int key){
if(n == null || key == n.value ){
return n;
}
if(key < n.value){
return search(n.left,key);
}
else{
return search(n.right,key);
}
}
public static Node treeMinimum(Node x){
if(x == null){
return null;
}
while(x.left != null){
x = x.left;
}
return x;
}
public static Node treeMaximum(Node x){
if(x == null){
return null;
}
while(x.right != null){
x = x.right;
}
return x;
}
public static Node treeSuccessor(Btree t,Node x){
if (x.right == null){
return treeMinimum(x.right);
}
Node y = getParent(t,x);
while(y != null && x == y.right){
x = y;
y = getParent(t,y);
}
return y;
}
public static Btree insert(Btree t,Node z){
Node y = null;
Node x = t.root;
while(x != null){
y = x;
if(z.value < x.value)
x = x.left;
else
x = x.right;
}
Node tmp = getParent(t,z);
tmp = y;
if(y == null){
t.root = z;
}
else if(z.value < y.value)
y.left = z;
else
y.right = z;
return t;
}
public static Btree delete(Btree t,Node z){
Node y,x;
if (z.left == null || z.right == null)
y = z;
else
y = treeSuccessor(t,z);
if (y.left != null)
x = y.left;
else
x = y.right;
if (x != null){
Node tmp = getParent(t,x);
tmp = getParent(t,y);
}
if (getParent(t,y) == null ){
t.root = x;
}
else{
if( y == getParent(t,y).left ){
getParent(t,y).left = x;
}
else{
getParent(t,y).right = x;
}
}
if(y != z){
z.value = y.value;
}
return t;
}
public static void main(String[] args){
Btree test = new Btree();
Node n1 = new Node(6);
Node n2 = new Node(3);
Node n3 = new Node(9);
Node n4 = new Node(1);
Node n5 = new Node(16);
Node n6 = new Node(4);
Node n7 = new Node(2);
Node n8 = new Node(11);
Node n9 = new Node(13);
test = insert(test,n1);
test = insert(test,n2);
test = insert(test,n3);
test = insert(test,n4);
test = insert(test,n5);
test = insert(test,n6);
test = insert(test,n7);
test = insert(test,n8);
test = insert(test,n9);
inorderWalk(test.root);
System.out.println();
test = delete(test,n8);
inorderWalk(test.root);
System.out.println();
test = delete(test,n5);
inorderWalk(test.root);
System.out.println();
test = delete(test,n2);
inorderWalk(test.root);
System.out.println();
test = delete(test,n1);
inorderWalk(test.root);
}
}
The main problem is with the remove part, sometimes it is working as intended, sometimes removing wrongly and sometimes null pointer exception. What can be the issue ?
Ps: this is NOT a homework
Some immediate problems with your code: your treeSuccessor starts with
if (x.right == null){
return treeMinimum(x.right);
}
which should be if (x.right != null), of course.
Your insert code has the lines
Node tmp = getParent(t,z);
tmp = y;
where you assign to tmp and immediately assign to it again. It doesn't seem to me that you need these lines at all, since you don't use tmp further on. At this moment, you have y being the node to whose child z gets inserted, so just delete these lines.
Again, in delete, you have the lines
if (x != null){
Node tmp = getParent(t,x);
tmp = getParent(t,y);
}
where you don't actually do anything, since tmp is not visible outside this snippet. And further on, in delete, you repeat the expression getParent(t,y), which can be an expensive operation, so you should compute it only once and assign it to some variable.
But in general, your code, though it seems correct (probably apart from delete, which I did not understand completely but which looks suspicious), does not much resemble typical binary tree code. You don't really need the getParent and treeSuccessor methods to implement search, insert, and delete. The basic structure that you have for search works for the others too, with the following modifications:
with insert, when you get to a null link, instead of returning null, insert the element to that point
with delete, when you find the element, if it has only one (or no) child, replace it with that child, and if it has two children, replace it with either the maximum of the left child tree or the minimum of the right child tree
Both of these require in addition that you keep track of the parent node while descending into the tree, but that's the only modification you need to make to search. In particular, there is never any need to go upwards in the tree (which treeSuccessor will do).
First of all, your implementation got nothing to do with object orientation (except using objects). The insert and delete operations for example should operate ON the Tree.
Besides, I would recommend to implement the Node class as a static member of the Tree class.
public class Tree {
private Node root = null;
// remainder omitted
public boolean insert(int element) {
if (isEmpty()) {
root = new Node(element);
return true; // empty tree, Node could be inserted, return true
}
Node current = root; // start at root
Node parent; // the current Node's parent
do {
parent = current;
if (element < current.element) {
current = current.left; // go to left
} else if (element > current.element) {
current = current.right; // go to right
} else {
return false; // duplicates are NOT allowed, element could not be inserted -> return false
} while (current != null);
Node node = new Node(element);
if (element < current.element) {
parent.left = node;
} else {
parent.right = node;
}
return true; // node successfully inserted
}
public boolean isEmpty() {
return root == null;
}
private static class Node { // static member class
Node left = null;
Node right = null;
final int element;
Node(int element) {
this.element = element;
}
}
}
...what is up with your delete code? It doesn't make a lot of sense. I would consider rewriting it in a more logical way. Without the meaningless single-letter variable names. And add comments!
One possible algorithm is:
Get the parent of the node to delete
Get the right-most node of the left subtree, or the leftmost node of the right subtree
Remove the node to delete and replace it with the node you found
Rebalance the tree
...or, if you want to hack up this stuff so it's right, I'd start looking at the
if (x != null){
Node tmp = getParent(t,x);
tmp = getParent(t,y);
}
part, because that's clearly wrong.
I'll have to side with Anon and go for the rewrite. The null pointers come from your getParent function (which explicitly returns nulls along other things). So I would start there and fix the function(s) so that they return one thing and one thing only at the end of the function.
Here is the complete Implementation of Binary Search Tree In Java
insert,search,countNodes,traversal,delete,empty,maximum & minimum node,find parent node,print all leaf node, get level,get height, get depth,print left view, mirror view
import java.util.NoSuchElementException;
import java.util.Scanner;
import org.junit.experimental.max.MaxCore;
class BSTNode {
BSTNode left = null;
BSTNode rigth = null;
int data = 0;
public BSTNode() {
super();
}
public BSTNode(int data) {
this.left = null;
this.rigth = null;
this.data = data;
}
#Override
public String toString() {
return "BSTNode [left=" + left + ", rigth=" + rigth + ", data=" + data + "]";
}
}
class BinarySearchTree {
BSTNode root = null;
public BinarySearchTree() {
}
public void insert(int data) {
BSTNode node = new BSTNode(data);
if (root == null) {
root = node;
return;
}
BSTNode currentNode = root;
BSTNode parentNode = null;
while (true) {
parentNode = currentNode;
if (currentNode.data == data)
throw new IllegalArgumentException("Duplicates nodes note allowed in Binary Search Tree");
if (currentNode.data > data) {
currentNode = currentNode.left;
if (currentNode == null) {
parentNode.left = node;
return;
}
} else {
currentNode = currentNode.rigth;
if (currentNode == null) {
parentNode.rigth = node;
return;
}
}
}
}
public int countNodes() {
return countNodes(root);
}
private int countNodes(BSTNode node) {
if (node == null) {
return 0;
} else {
int count = 1;
count += countNodes(node.left);
count += countNodes(node.rigth);
return count;
}
}
public boolean searchNode(int data) {
if (empty())
return empty();
return searchNode(data, root);
}
public boolean searchNode(int data, BSTNode node) {
if (node != null) {
if (node.data == data)
return true;
else if (node.data > data)
return searchNode(data, node.left);
else if (node.data < data)
return searchNode(data, node.rigth);
}
return false;
}
public boolean delete(int data) {
if (empty())
throw new NoSuchElementException("Tree is Empty");
BSTNode currentNode = root;
BSTNode parentNode = root;
boolean isLeftChild = false;
while (currentNode.data != data) {
parentNode = currentNode;
if (currentNode.data > data) {
isLeftChild = true;
currentNode = currentNode.left;
} else if (currentNode.data < data) {
isLeftChild = false;
currentNode = currentNode.rigth;
}
if (currentNode == null)
return false;
}
// CASE 1: node with no child
if (currentNode.left == null && currentNode.rigth == null) {
if (currentNode == root)
root = null;
if (isLeftChild)
parentNode.left = null;
else
parentNode.rigth = null;
}
// CASE 2: if node with only one child
else if (currentNode.left != null && currentNode.rigth == null) {
if (root == currentNode) {
root = currentNode.left;
}
if (isLeftChild)
parentNode.left = currentNode.left;
else
parentNode.rigth = currentNode.left;
} else if (currentNode.rigth != null && currentNode.left == null) {
if (root == currentNode)
root = currentNode.rigth;
if (isLeftChild)
parentNode.left = currentNode.rigth;
else
parentNode.rigth = currentNode.rigth;
}
// CASE 3: node with two child
else if (currentNode.left != null && currentNode.rigth != null) {
// Now we have to find minimum element in rigth sub tree
// that is called successor
BSTNode successor = getSuccessor(currentNode);
if (currentNode == root)
root = successor;
if (isLeftChild)
parentNode.left = successor;
else
parentNode.rigth = successor;
successor.left = currentNode.left;
}
return true;
}
private BSTNode getSuccessor(BSTNode deleteNode) {
BSTNode successor = null;
BSTNode parentSuccessor = null;
BSTNode currentNode = deleteNode.left;
while (currentNode != null) {
parentSuccessor = successor;
successor = currentNode;
currentNode = currentNode.left;
}
if (successor != deleteNode.rigth) {
parentSuccessor.left = successor.left;
successor.rigth = deleteNode.rigth;
}
return successor;
}
public int nodeWithMinimumValue() {
return nodeWithMinimumValue(root);
}
private int nodeWithMinimumValue(BSTNode node) {
if (node.left != null)
return nodeWithMinimumValue(node.left);
return node.data;
}
public int nodewithMaximumValue() {
return nodewithMaximumValue(root);
}
private int nodewithMaximumValue(BSTNode node) {
if (node.rigth != null)
return nodewithMaximumValue(node.rigth);
return node.data;
}
public int parent(int data) {
return parent(root, data);
}
private int parent(BSTNode node, int data) {
if (empty())
throw new IllegalArgumentException("Empty");
if (root.data == data)
throw new IllegalArgumentException("No Parent node found");
BSTNode parent = null;
BSTNode current = node;
while (current.data != data) {
parent = current;
if (current.data > data)
current = current.left;
else
current = current.rigth;
if (current == null)
throw new IllegalArgumentException(data + " is not a node in tree");
}
return parent.data;
}
public int sibling(int data) {
return sibling(root, data);
}
private int sibling(BSTNode node, int data) {
if (empty())
throw new IllegalArgumentException("Empty");
if (root.data == data)
throw new IllegalArgumentException("No Parent node found");
BSTNode cureent = node;
BSTNode parent = null;
boolean isLeft = false;
while (cureent.data != data) {
parent = cureent;
if (cureent.data > data) {
cureent = cureent.left;
isLeft = true;
} else {
cureent = cureent.rigth;
isLeft = false;
}
if (cureent == null)
throw new IllegalArgumentException("No Parent node found");
}
if (isLeft) {
if (parent.rigth != null) {
return parent.rigth.data;
} else
throw new IllegalArgumentException("No Sibling is there");
} else {
if (parent.left != null)
return parent.left.data;
else
throw new IllegalArgumentException("No Sibling is there");
}
}
public void leafNodes() {
if (empty())
throw new IllegalArgumentException("Empty");
leafNode(root);
}
private void leafNode(BSTNode node) {
if (node == null)
return;
if (node.rigth == null && node.left == null)
System.out.print(node.data + " ");
leafNode(node.left);
leafNode(node.rigth);
}
public int level(int data) {
if (empty())
throw new IllegalArgumentException("Empty");
return level(root, data, 1);
}
private int level(BSTNode node, int data, int level) {
if (node == null)
return 0;
if (node.data == data)
return level;
int result = level(node.left, data, level + 1);
if (result != 0)
return result;
result = level(node.rigth, data, level + 1);
return result;
}
public int depth() {
return depth(root);
}
private int depth(BSTNode node) {
if (node == null)
return 0;
else
return 1 + Math.max(depth(node.left), depth(node.rigth));
}
public int height() {
return height(root);
}
private int height(BSTNode node) {
if (node == null)
return 0;
else
return 1 + Math.max(height(node.left), height(node.rigth));
}
public void leftView() {
leftView(root);
}
private void leftView(BSTNode node) {
if (node == null)
return;
int height = height(node);
for (int i = 1; i <= height; i++) {
printLeftView(node, i);
}
}
private boolean printLeftView(BSTNode node, int level) {
if (node == null)
return false;
if (level == 1) {
System.out.print(node.data + " ");
return true;
} else {
boolean left = printLeftView(node.left, level - 1);
if (left)
return true;
else
return printLeftView(node.rigth, level - 1);
}
}
public void mirroeView() {
BSTNode node = mirroeView(root);
preorder(node);
System.out.println();
inorder(node);
System.out.println();
postorder(node);
System.out.println();
}
private BSTNode mirroeView(BSTNode node) {
if (node == null || (node.left == null && node.rigth == null))
return node;
BSTNode temp = node.left;
node.left = node.rigth;
node.rigth = temp;
mirroeView(node.left);
mirroeView(node.rigth);
return node;
}
public void preorder() {
preorder(root);
}
private void preorder(BSTNode node) {
if (node != null) {
System.out.print(node.data + " ");
preorder(node.left);
preorder(node.rigth);
}
}
public void inorder() {
inorder(root);
}
private void inorder(BSTNode node) {
if (node != null) {
inorder(node.left);
System.out.print(node.data + " ");
inorder(node.rigth);
}
}
public void postorder() {
postorder(root);
}
private void postorder(BSTNode node) {
if (node != null) {
postorder(node.left);
postorder(node.rigth);
System.out.print(node.data + " ");
}
}
public boolean empty() {
return root == null;
}
}
public class BinarySearchTreeTest {
public static void main(String[] l) {
System.out.println("Weleome to Binary Search Tree");
Scanner scanner = new Scanner(System.in);
boolean yes = true;
BinarySearchTree tree = new BinarySearchTree();
do {
System.out.println("\n1. Insert");
System.out.println("2. Search Node");
System.out.println("3. Count Node");
System.out.println("4. Empty Status");
System.out.println("5. Delete Node");
System.out.println("6. Node with Minimum Value");
System.out.println("7. Node with Maximum Value");
System.out.println("8. Find Parent node");
System.out.println("9. Count no of links");
System.out.println("10. Get the sibling of any node");
System.out.println("11. Print all the leaf node");
System.out.println("12. Get the level of node");
System.out.println("13. Depth of the tree");
System.out.println("14. Height of Binary Tree");
System.out.println("15. Left View");
System.out.println("16. Mirror Image of Binary Tree");
System.out.println("Enter Your Choice :: ");
int choice = scanner.nextInt();
switch (choice) {
case 1:
try {
System.out.println("Enter Value");
tree.insert(scanner.nextInt());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 2:
System.out.println("Enter the node");
System.out.println(tree.searchNode(scanner.nextInt()));
break;
case 3:
System.out.println(tree.countNodes());
break;
case 4:
System.out.println(tree.empty());
break;
case 5:
try {
System.out.println("Enter the node");
System.out.println(tree.delete(scanner.nextInt()));
} catch (Exception e) {
System.out.println(e.getMessage());
}
case 6:
try {
System.out.println(tree.nodeWithMinimumValue());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 7:
try {
System.out.println(tree.nodewithMaximumValue());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 8:
try {
System.out.println("Enter the node");
System.out.println(tree.parent(scanner.nextInt()));
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 9:
try {
System.out.println(tree.countNodes() - 1);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 10:
try {
System.out.println("Enter the node");
System.out.println(tree.sibling(scanner.nextInt()));
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 11:
try {
tree.leafNodes();
} catch (Exception e) {
System.out.println(e.getMessage());
}
case 12:
try {
System.out.println("Enter the node");
System.out.println("Level is : " + tree.level(scanner.nextInt()));
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 13:
try {
System.out.println(tree.depth());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 14:
try {
System.out.println(tree.height());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 15:
try {
tree.leftView();
System.out.println();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 16:
try {
tree.mirroeView();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
default:
break;
}
tree.preorder();
System.out.println();
tree.inorder();
System.out.println();
tree.postorder();
} while (yes);
scanner.close();
}
}
As per my understanding following implementation done for binary search tree, kindly look
into that and let me know any feedback required
Insertion
InOrderTraversal
Search
Removal
Please take a look at the main method. so, Please provide your's feedback to improve further from my side.
public class BinarySearchTree {
private Node root;
public BinarySearchTree() {
root = null;
}
public BinarySearchTree(int rootData) {
root = new Node(rootData);
}
public void insertElement(int element,Node parent) {
Node temp = root;
if(parent!=null) temp = parent;
if(temp!=null) {
Node node = new Node(element);
if(element<temp.getData()) {
if(temp.getLeft()!=null)
insertElement(element, temp.getLeft());
else
temp.setLeft(node);
}else if(element>temp.getData()) {
if(temp.getRight()!=null)
insertElement(element, temp.getRight());
else
temp.setRight(node);
}
}
}
public void traverseInOrder() {
if(root!=null) {
traverse(root.getLeft());
System.out.println(root.getData());
traverse(root.getRight());
}
}
public void traverse(Node temp) {
if(temp!=null) {
traverse(temp.getLeft());
System.out.println(temp.getData());
traverse(temp.getRight());
}
}
public int searchElement(int element,Node node) {
Node temp = root;
if(node!=null) temp = node;
if(temp!=null) {
if(temp.getData()<element) {
if(temp.getRight()!=null)
return searchElement(element, temp.getRight());
}else if(temp.getData()>element) {
if(temp.getLeft()!=null)
return searchElement(element,temp.getLeft());
}else if(temp.getData()==element){
return temp.getData();
}
}
return -1;
}
public void remove(int element,Node node,Node predecer) {
Node temp = root;
if(node!=null) temp = node;
if(temp!=null) {
if(temp.getData()>element) {
remove(element, temp.getLeft(), temp);
}else if(temp.getData()<element) {
remove(element, temp.getRight(), temp);
}else if(element==temp.getData()) {
if(temp.getLeft()==null && temp.getRight()==null) {
if(predecer.getData()>temp.getData()) {
predecer.setLeft(null);
}else if(predecer.getData()<temp.getData()) {
predecer.setRight(null);
}
}else if(temp.getLeft()!=null && temp.getRight()==null) {
predecer.setRight(temp.getLeft());
}else if(temp.getLeft()==null && temp.getRight()!=null) {
predecer.setLeft(temp.getRight());
}else if(temp.getLeft()!=null && temp.getRight()!=null) {
Node leftMostElement = findMaximumLeft(temp.getLeft());
if(leftMostElement!=null) {
remove(leftMostElement.getData(), temp, temp);
temp.setData(leftMostElement.getData());
}
}
}
}
}
public Node findMaximumLeft(Node parent) {
Node temp = parent;
if(temp.getRight()!=null)
return findMaximumLeft(temp.getRight());
else
return temp;
}
public static void main(String[] args) {
BinarySearchTree bs = new BinarySearchTree(10);
bs.insertElement(29, null);
bs.insertElement(19, null);
bs.insertElement(209, null);
bs.insertElement(6, null);
bs.insertElement(7, null);
bs.insertElement(17, null);
bs.insertElement(37, null);
bs.insertElement(67, null);
bs.insertElement(-7, null);
bs.remove(6, null, null);
bs.traverseInOrder();}}