The following is my binary search implementation in Java:
package com.solo.workouts.collections.Tree;
import com.solo.workouts.Implementors.Util;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Objects;
/*
@author soloworld
@since 1.o
*/
public class BinarySearchTree<T> {
private Comparator comparator;
private Node<T> root;
private BinarySearchTree(Comparator comparator , T type) {
this.comparator = comparator;
}
private BinarySearchTree(Comparator comparator) {
this(comparator,null);
}
public static BinarySearchTree plantTree(Comparator comparator)
{
Objects.requireNonNull(comparator ,"requires an comparator . compartor canot be null");
return new BinarySearchTree(comparator);
}
public void add(T element){
Node<T> node =null;
if(root==null)
{
node = new Node<>(element);
root = node;
}
else {
Node<T> currentnode = root;
while(currentnode !=null) {
int result = compare(currentnode, new Node<>(element));
if (result <= 0) {
if (currentnode.leftNode == null) {
currentnode.leftNode = new Node<>(element);
currentnode = null;
} else
currentnode = currentnode.leftNode;
} else {
if (currentnode.rightNode == null) {
currentnode.rightNode = new Node<>(element);
currentnode = null;
} else
currentnode = currentnode.rightNode;
}
}
}
}
public boolean containsElement(Object e){
Objects.requireNonNull(e);
Node<T> currentnode = new Node<>((T) e);
return contains(currentnode);
}
private boolean contains(Node<T> node) {
Objects.requireNonNull(node);
Node<T> searchnode=null;
Node<T> currentnode =root;
while(searchnode==null &&
currentnode!=null) {
int value = compare(currentnode, node);
if(value ==0)
searchnode = currentnode;
else if(value<0)
currentnode = currentnode.leftNode;
else
currentnode = currentnode.rightNode;
}
return searchnode !=null;
}
private int compare(Node<T> currentnode, Node<T> element) {
Objects.requireNonNull(currentnode);
Objects.requireNonNull(element);
Objects.requireNonNull(comparator);
return comparator.compare(element.element,currentnode.element);
}
private Node<T> getnode(T element) {
Objects.requireNonNull(element);
Node<T> node = new Node<>(element,null,null);
Node<T> currentnode = root;
while (currentnode!=null && 0!= compare(currentnode,node)) {
int value = compare(currentnode,node);
if(value <0) {
currentnode = currentnode.leftNode;
}else {
currentnode = currentnode.rightNode;
}
}
return currentnode;
}
private <T> Node<T> getpredecessoe(Node<T> node) {
Node<T> predecessor = null;
return predecessor;
}
public T getsuccessor(T element) {
Objects.requireNonNull(element);
var node = getnode(element);
var successor = getsuccessor(node);
if(successor!=null)
return successor.element;
return null;
}
private Node<T> getsuccessor(Node<T> node) {
Node<T> successor = root;
if(node.rightNode!=null) {
successor = node.rightNode;
while (successor.leftNode != null) {
successor = successor.leftNode;
}
}
else {
successor = null;
Node<T> cureentnode = root;
while (cureentnode!= null &&0!= compare(cureentnode,node) ) {
int compare = compare(cureentnode,node);
if(compare <=0){
successor = cureentnode;
cureentnode = cureentnode.leftNode;
}
else
cureentnode = cureentnode.rightNode;
}
}
return successor;
}
public boolean deleteNode(T element) {
var node =getnode(element);
if(node== null)
return false;
if(node.leftNode ==null && node.rightNode == null)
unlinkNode(node);
else if(node.leftNode!=null && node.rightNode!=null) {
var parent = getParent(node);
var successor = getsuccessor(node);
unlinkSuccessor(successor);
successor.leftNode = node.leftNode;
successor.rightNode = node.rightNode;
linkSuccessorWithParent(parent,successor);
}
else {
var parentNode = getParent(node);
var childNode = node.leftNode!= null ? node.leftNode : node.rightNode;
int compare = compare(parentNode,childNode);
if(compare <=0)
parentNode.leftNode = childNode;
else
parentNode.rightNode = childNode;
node = null;
}
return node == null;
}
private void linkSuccessorWithParent(Node<T> parent, Node<T> successor) {
int compare = compare(parent,successor);
if(compare<=0)
parent.leftNode = successor;
else
parent.rightNode = successor;
}
public void unlinkNode(Node<T> node) {
var parent = getParent(node);
Objects.requireNonNull(parent);
Objects.requireNonNull(node);
int compare = compare(parent,node);
if(compare <=0)
parent.leftNode = null;
else
parent.rightNode = null;
}
private void unlinkSuccessor(final Node<T> successor) {
var parent = getParent(successor);
unlinkNode( successor);
if(successor.rightNode != null)
parent.leftNode = successor.rightNode;
}
private Node<T> getParent(Node<T> childnode) {
var parentnode = root;
var currentnode = root;
Objects.requireNonNull(childnode);
while (0!= compare(currentnode,childnode)) {
parentnode = currentnode;
int compare = compare(currentnode,childnode);
if(compare<0)
currentnode = currentnode.leftNode;
else if(compare >0)
currentnode = currentnode.rightNode;
}
return parentnode;
}
public void morrisTreewalk() {
}
private static class Node<T> {
T element;
Node<T> leftNode ;
Node<T> rightNode;
Node(T element, Node<T> leftNode, Node<T> rightNode) {
this.element = element;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
Node(T element) {
this(element,null,null);
}
}
}
Even though this data structure passes basic test cases I was not sure what will be the performance if the amount of input is high. Also, if there is any optimisation, please tell.