目录
首先需要定义一个结点类
结点类
public class BinNode<K,V> {
public K key;
public V value;
private BinNode<K,V> left;
private BinNode<K,V> right;
public BinNode(K key,V value){
this.key=key;
this.value=value;
}
public BinNode<K, V> getLeft() {
return left;
}
public void setLeft(BinNode<K, V> left) {
this.left = left;
}
public BinNode<K,V> getRight() {
return right;
}
public void setRight(BinNode<K,V> right) {
this.right = right;
}
}
再定义一个BST接口,逐个实现接口中的方法
插入
根节点空插入根节点,等于更新value,小于找左子树,大于找右子树
public void insert(String key, String value) {
if(root==null){
root=new BinNode<>(key, value);
return;
}
BinNode<String,String>cur=root,tmp=new BinNode<>(key, value);
while (cur!=null)
if (cur.value.compareTo(value)<0){
if (cur.getRight()==null){
cur.setRight(tmp);
return;
}
cur=cur.getRight();
}
else if(cur.value.compareTo(value)>0){
if (cur.getLeft()==null){
cur.setLeft(tmp);
return;
}
cur=cur.getLeft();
}
else cur.value=value;
}
删除
三种情况,但前两种可以当成第三种处理
为叶结点:直接将指向其的指针置为null
有一个子结点:直接将指向其的指针置为该子结点
有两个子结点:找到待删结点左子树的最大结点或右子树的最小结点(寻找最小值),将待删结点值替换为找到的结点,并删除原本找到的结点(删除最小值)。
这里需要两个额外的方法:寻找最小值和删除最小值
寻找最小值
一直递归找左子结点直到左子结点为空,说明找到最小结点,返回。
private BinNode getMin(BinNode root){
if (root.getLeft()==null)return root;
else return getMin(root.getLeft());
}
删除最小值并返回其父结点
一直递归找左子结点直到左子结点为空,说明找到最小结点,返回右子结点(可以是null),此时的root是最小结点的父结点,此时的实参是最小结点的右结点(如果不为null则一定小于root)。
实参赋给root的左子结点,相当于删除最小结点但保留其子结点。
private BinNode deleteMin(BinNode root){
if (root.getLeft()==null)//左子树为空,说明找到最小结点,返回右子树(可以是null)
return root.getRight();
else{
//一直找左子树直到找到,此时的root是最小结点的父结点
// 此时的实参是最小结点的右结点(如果不为null则一定小于root)
// 将实参赋给root的左子结点,相当于删除最小结点但保留其子结点
root.setLeft(deleteMin(root.getLeft()));
return root;
}
}
删除结点
public String remove(String key) {
return removeHelp(root,key).value;
}
private BinNode<String,String> removeHelp(BinNode<String,String>root,String key){
if (root==null)return null;
//查找待删除结点
if (root.key.compareTo(key)>0)root.setLeft(removeHelp(root.getLeft(),key));
else if (root.key.compareTo(key)<0)root.setRight(removeHelp(root.getRight(),key));
//找到该结点
else {
if(root.getLeft()==null)root=root.getRight();
else if(root.getRight()==null)root=root.getLeft();
else {
BinNode<String,String> tmp=getMin(root.getRight());//找到右子树上的最小结点
root.key=tmp.key;root.value=tmp.value;//将待删结点信息替换为最小结点的信息
root.setRight(deleteMin(root.getRight()));//删除右子树上的最小结点
}
}
return root;
}
查找
等于返回,小于找左子树,大于找右子树,为空则没有找到
public String search(String key) {
BinNode<String,String> curr=root;
while(curr!=null){
if (Objects.equals(key, curr.key))return curr.value;
else if (key.compareTo(curr.key)<0)curr= curr.getLeft();
else curr= curr.getRight();
}
return null;
}
计算深度
通过递归求左右子树深度最大值
private int getHeight(BinNode root){
if (root==null)return 0;
int h1=0,h2=0;
h1=getHeight(root.getLeft());
h2=getHeight(root.getRight());
if (h1>h2)return h1+1;
else return h2+1;
}
中序遍历(由小到大输出二叉检索树)
先遍历左子树,然后访问根结点,最后遍历右子树。
先访问根结点的左子节点,直到为空,就可以输出第一个结点,此结点视为根结点,下一步访问其右子结点。对于以其右子结点为根的右子树进行中序遍历,即递归调用该方法。右子树遍历完之后,回退到第一个输出结点的父结点并将其输出,再对该父结点的右子树进行中序遍历,如此往复。
public void inorderTraversal(BinNode root){
if (root==null)return;
inorderTraversal(root.getLeft());
System.out.println("["+root.key+"---<"+root.value+">]");
inorderTraversal(root.getRight());
}