二叉搜索树的查找插入和删除

1. 什么是二叉搜索树

  • 对二叉搜索树进行中序遍历,其结果是有序的
  • 若左右子树不为空,左子树上所有节点的值小于根节点的值,右子树上所有节点的值大于根节点的值

2. 实现二叉搜索树的 查找、插入、删除操作

2.1 先准备一个二叉搜索树的节点

class BinaryNode{
    int key;
    int value;
    BinaryNode left;
    BinaryNode right;

    public BinaryNode(int key, int value) {
        this.key = key;
        this.value = value;
    }
}

2.2 准备根节点

BinaryNode root=null;

2.3 查找,get()方法的实现

思路

  • 若key小于根节点的值,在根节点的左子树中找
  • 若key大于根节点的值,在根节点的右子树中找

代码

public Integer get(int key){
    BinaryNode cur=root;
    while(cur!=null){
        if(key<cur.key){
            cur=cur.left;
        }else if(key>cur.key){
            cur=cur.right;
        }else{
            return cur.value;
        }
    }
    return null;
}

2.4 增加键值对,put()方法的实现

思路

  • 定义两个引用,parent和cur
  • 如果key已经存在,那么只需要修改key的value即可
  • 如果key不存在,找到待插元素的合适位置,进行插入即可

代码

public void put(int key,int value){
    BinaryNode parent=null;
    BinaryNode cur=root;
    while(cur!=null){
        if(key<cur.key){
            parent=cur;
            cur=cur.left;
        }else if(key>cur.key){
            parent=cur;
            cur=cur.right;
        }else{
            cur.value=value;
            return;
        }
    }
    //找到插入的位置了,此时cur指向空
    //具体要插入到parent的左子树还是右子树,只需要判断key大于还是小于parent的key
    BinaryNode newNode=new BinaryNode(key,value);
    if(key<parent.key){
        parent.left=newNode;
    }else{
        parent.right=newNode;
    }
}

2.5 删除键值对,remove()方法实现

思路

首先根据 key 找到待删节点 cur,记录其位置和其父节点 parent 的位置

分为三种情况:

  • ① cur的左子树为空

          cur是根节点;cur是parent的左子树;cur是parent的右子树

  • ② cur的右子树为空

          cur是根节点;cur是parent的左子树;cur是parent的右子树

  • ③ cur的左右子树均不为空

          从待删节点的右子树中找到一个key最小的节点goat,采用移形换影,将goat的信息赋给cur,此时也就相当于cur不存在了

          由于goat是cur右子树的最小值,所以是一路向左跑,即最终goat一定是没有左子树的。

          删掉goat即可,所以将其称为替罪羊节点

public void remove(int key){
    //首先找到要删除键值对的位置
    BinaryNode parent=null;
    BinaryNode cur=root;
    while(cur!=null){
        if(key<cur.key){
            parent=cur;
            cur=cur.left;
        }else if(key>cur.key){
            parent=cur;
            cur=cur.right;
        }else{
            //找到要删除的节点了
            removeNode(parent,cur);
        }
    }
}
public void removeNode(BinaryNode parent,BinaryNode cur) {
    if(cur.left==null){
        if(root==cur){
            root=cur.right;
        }else if(parent.left==cur){
            parent.left=cur.right;
        }else{
            parent.right=cur.right;
        }
    }else if(cur.right==null){
        if(root==cur){
            root=cur.left;
        }else if(parent.left==cur){
            parent.left=cur.left;
        }else{
            parent.right=cur.left;
        }
    }else{
        BinaryNode parentGoat=cur;
        BinaryNode goat=cur.right;
        //从待删节点的右子树中找到key最小的节点goat
        while(goat.left!=null){
            parentGoat=goat;
            goat=goat.left;
        }
        //将goat的信息赋给待删节点cur,相当于cur被删除了,此时只需要删除goat就行
        cur.key=goat.key;
        cur.value=goat.value;
        //由于goat是一路向左找的,所以goat一定没有左子树
        if(parentGoat.left==goat){
            parentGoat.left=goat.right;
        }else{
            parentGoat.right=goat.right;
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值