【Java数据结构】二叉搜索树的查找插入删除

什么是二叉搜索树?

     二叉搜索树又称二叉排序数(它可能也是棵空树),简单的来说 根节点左边 比根节点小根节点右边比根节点大。

话不多说 上个图 便于理解

具有的性质

二叉搜索树操作代码实现

1.查找(查找key是否在二叉搜索树中)

 代码实现

//二叉搜索树
class Node {
    public int val;
    public Node left;
    public Node right;
    public Node(int val) {
        this.val = val;
    }
}

public class BinarySearchTree {
   
  public Node root = null;//根节点
//查找key在不在二叉搜索树中
public Node search(int key) {
     Node cur = root;
     //这里分三种情况
     while (cur != null) {
         //1.如果cur的值刚好等于key
         if(cur.val == key) {
             return cur;
             //2.如果cur.val 小于 key
             //那么要查找的key 在 其右子树
         }else if(cur.val < key) {
             cur = cur .right;
             //3.如果cur.val 大于 key
             //那么要查找的 key 在 其左子树
         }else {
             cur = cur.left;
         }
     }
     return null;//代表没有这个数据
}

2.插入(对于二叉搜素数来说,插入的数据一定是叶子节点)//这一点很重要,知道了就很好写

代码实现

//二叉搜索树插入一个key
    //对于二叉搜索树来说 插入的数据一定是 叶子节点
    public boolean insert(int val) {
        
//如果是空数 直接插入
    if(root == null) {
        root = new Node(val);//root等于新插入的节点,节点的值为val
        return true;
    }
    //如果不是 空数 那么 接下来我们去找叶子节点
    Node cur = root;//一样的 用cur代替root
    Node parent = null;//用一个双亲节点
    while (cur != null) {
        //1,如果val的值大于cur 那么val 在cur的右子树
        if(cur.val < val) {
            parent = cur;
            cur = cur.right;
            //2.如果val的值刚好等于cur的值 不能插入
        }else if(cur.val == val) {
            return false;//不能有相同的数据进行插入
            //3.如果val的值小于cur 那么val 在cur的左子树
        }else {
            parent = cur;
            cur = cur.left;
        }
    }
    //找到叶子节点以后我们要去比较parent.val 和val的大小再进行插入
    Node node = new Node(val);//新节点val
    if(parent.val < val) {
        parent.right = node;//这里根据二叉搜索树的性质,parent为根节点
        //val比根节点大所以在根节点右边
    }else {
        parent.left = node;
    }
    return true;
}

3.删除(难点)

1.当cur.left == null的时候

 

 

 2.当cur.right == null 的时候

 

 3.当cur.left != null && cur.right != null 的时候

需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题
 

用tap代替cur  cur.right = ta 如果 ta.left == null 了 交换 ta和 cur的值

 这里 是 ta 在tap 左边的情况

这里是 ta 在tap 右边的情况

 

//二叉搜素数 删除操作(难点)
    public void  remove(int key) {
        Node cur = root;
        Node parent = null;
        while (cur != null) {
            if(cur.val == key) {
                removeNode(cur,parent);
                break;
            }else if(cur.val<key) {
                parent = cur;
                cur = cur.right;
            }else {
                parent = cur;
                cur = cur.left;
            }
        }
    }

    public void removeNode(Node cur,Node parent) {
        //第一种情况 cur.left == null
        if (cur.left == null) {
            //1.cur是root 则 root = cur.right
            if (cur == root) {
                root = cur.right;
                //2.cur不是root cur是parent.left
            } else if (cur == parent.left) {
                parent.left = cur.right;
                //3,cur不是root cur是parent.right
            } else {
                parent.right = cur.right;
            }
            //第二种情况 cur.right == null
        } else if (cur.right == null) {
            //1,cur是root root = cur.left
            if (cur == root) {
                root = cur.left;
                //2.cur不是root cur是parent.left
            } else if (cur == parent.left) {
                parent.left = cur.left;
                //3,cur不是root cur是parent.right
            } else {
                parent.right = cur.left;
            }
            //第三种情况 cur.left!=null && cur.right!=null(难点)
            //1.cur的左树当中找最大值2.cur的右树当中找最小值
            //核心就是替换
        } else {
            Node targetParent = cur;
            Node targer = cur.right;
            //左树找不等于空的时候
            while (targer.left != null) {
                targetParent = targer;
                targer = targer.left;
            }
            cur.val = targer.val;//交换值
            //这里需要判断 ta 是在 tap的左边还是右边
            if (targer == targetParent.left) {
                targetParent.left = targer.right;
            } else {
                targetParent.right = targer.right;
            }
        }
    }
}

  • 22
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偷偷敲代码的青花瓷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值