一、 二叉搜索树简介
二叉搜索树是一棵左子树节点永远小于根节点,右子树永远大于根节点的二叉树
二、实现细节
1. 增加元素
- 每次增加都在叶子结点,当要增加的元素等于根节点的值的时候不做操作直接将该数返回。
- 当要增加的元素小于根节点的时候,在左子树加入该节点,并把左子树更新为增加节点后的左子树。
- 当大于根节点的时候,在子右树加入该节点,并把右子树更新为增加节点后的右子树子树。
2. 删除元素
-
当要删除的元素小于根节点的时候,在左子树删除该节点,并把左子树更新为删除节点后的左子树。
-
当要删除的元素大于根节点的时候,在右子树删除该节点,并把右子树更新为删除节点后的右子树。
-
当要删除的元素为根节点的时候,此时分为三种情况:
1. 左右子树都为空直接删除节点。
2. 只有一个子树,删除当前节点,将父节点指向该节点的指针指向该节点的唯一孩子节点。
3. 当该节点有两个孩子的时候,采取的办法就是找到大小离他最近的元素(左子树的最大值/右子树的最小值),将当前节点的值重置为离他最近的元素(左子树的最大值/右子树的最小值),将离他最近的元素所在的节点删除。
代码
public class BinarySearchTree <T extends Comparable> {
private BinaryNode <T>root;
public BinarySearchTree() {
}
public BinarySearchTree(T element) {
this.root = new BinaryNode<T>(element,null,null);
}
/**
* 在当前树上插入元素
* */
public void insert(T element){
root = insert(element,root);
}
/**
* 在树上插入元素并返回新树
* */
private BinaryNode<T> insert(T element,BinaryNode root){
if (root == null) //如过是空的时候直接新建节点返回-----即把新建的节点返回赋值给父节点的某个子树
return new BinaryNode<T>(element,null,null);
int flag = element.compareTo(root.element);
if (flag<0) //要插入的元素比当前元素小插入到左子树
root.left = insert(element,root.left);
else if (flag>0) //要插入的元素比当前元素大插入到右子树中
root.right = insert(element,root.right);
else //要插入的元素等于当前元素什么也不做---为了便于理解写出来
;
return root; //最后将插入好的树返回
}
public boolean contain(T element){
return contain(element, root);
}
/**
* 判断元素是否包含在树中
* */
private boolean contain(T element,BinaryNode root){
if(root==null)
return false;
boolean is;
int flag = element.compareTo(root.element);
if (flag<0)
is =contain(element,root.left); //没有找到在当前左子树上寻找
else if (flag>0)
is = contain(element,root.right); //没有找到在当前右子树上寻找
else
return true;
return is;
}
/**
* 删除元素
* */
public void remove(T element){
root = remove(element,root);
}
public BinaryNode<T> remove(T element,BinaryNode<T> root){
if (root!=null){
int flag = element.compareTo(root.element);
if(flag<0){
root.left = remove(element,root.left);
}
else if (flag>0){
root.right = remove(element,root.right);
}
else{
//当前的节点就是要删除的节点
//1. 没有孩子
if (root.left==null&&root.right==null){
return null;
}
//2. 有一个孩子
else if(root.left==null||root.right==null){
return root.left==null?root.right:root.left;//返回不为空的那个孩子
}
//3. 有两个孩子
else{
//将当前节点的值设置为距离他最近的节点的元素(遍历后在他后边),
//对应着右子树的最小值,左子树的最大值
//现在选择右子树的最小值
root.element = removeMin(root.right);
}
}
}
return root;
}
//将最小值删除并返回他的值
private T removeMin(BinaryNode<T> root){
BinaryNode <T> node = root;
BinaryNode <T> parent = root;
while(node.left!=null){
parent = node;
node = node.left;
}
parent.left = node.right;
return node.element;
}
private static class BinaryNode<T>{
T element;
BinaryNode<T> left;
BinaryNode<T> right;
public BinaryNode(T element, BinaryNode<T> left, BinaryNode<T> right) {
this.element = element;
this.left = left;
this.right = right;
}
}
public static void main(String[] args) {
BinarySearchTree<Integer> tree = new BinarySearchTree<>();
tree.insert(5);
tree.insert(3);
tree.insert(6);
tree.insert(4);
tree.insert(4);
boolean is = tree.contain(7);
tree.remove(3);
System.out.println(is);
System.out.println();
}
}