【Java】基本二叉搜索树讲解

1.概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  3. 它的左右子树也分别为二叉搜索树

在这里插入图片描述

int a [] = {5,3,4,1,7,8,2,6,0,9};

2. 操作-查找 search

在这里插入图片描述
代码实现 :

 public TreeNode search(int key){
        TreeNode cur=root;
        while (cur!=null){
            if (cur.val<key){
                cur=cur.right;
            }else if (cur.val==key){
                return cur;
            }else {
                cur=cur.left;
            }
        }
           return null;
    }

3.操作-插入 insert

  1. 如果树为空树,即根 == null,直接插入
    在这里插入图片描述

  2. 如果树不是空树,按照查找逻辑确定插入位置,插入新节点
    在这里插入图片描述

代码实现 :

 public boolean insert(int val){
        if (root==null){
            root=new TreeNode(val);
            return true;
        }
        TreeNode parent=null;
        TreeNode cur=root;
        while (cur!=null){
            if (cur.val<val){
                parent=cur;
                cur=cur.right;
            }else if (cur.val==val){
                return false;//不能有相同的数据
            }else {
                parent=cur;
                cur=cur.left;
            }
        }
        TreeNode node=new TreeNode(val);
        if (parent.val<val){
            parent.right=node;
        }else {
            parent.left=node;
        }
        return true;
    }

4. (难点)操作-删除 remove

删除remove操作比较复杂,需要画图分情况讨论 :

  1. 待删除结点为 cur, 待删除结点的双亲结点为 parent

4.1 cur.left == null

  1. cur 是 root,则 root = cur.right
    在这里插入图片描述

  2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.right
    在这里插入图片描述

  3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.right
    在这里插入图片描述

4.2 cur.right == null

  1. cur 是 root,则 root = cur.left
    在这里插入图片描述

  2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.left
    在这里插入图片描述

  3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.left
    在这里插入图片描述

4.3 cur.left != null && cur.right != null

  1. 需要在cur的左树当中 找最大值
  2. 或者在cur的右树当中 找最小值
  3. 使用替换法进行删除,用它的值填补到被删除节点中,再来处理该结点的删除问题

在这里插入图片描述
画图分析如下:
4. 需要删除cur如图为70,那我们就需要到右子树中找一个最小值75来与其替换(或者去左子树找最大值来与其替换)
在这里插入图片描述
5. 找到目标值75以后,再将其删除,如图所示(图为target==targetParent.left 情况
在这里插入图片描述
删除代码为: targetParent.left=target.right

  1. 如果为 target==targetParent.left 情况 :
    在这里插入图片描述
    删除代码为 targetParent.right=target.right;

代码实现 :

   public void remove(int key){
        TreeNode cur=root;
        TreeNode 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(TreeNode cur,TreeNode parent){
        if (cur.left==null){
            if (cur==root){
                root=cur.right;
            }else if (cur==parent.left){
                parent.left=cur.right;
            }else {
                parent.right=cur.right;
            }
        }else if (cur.right==null){
            if (cur==root){
                root=cur.left;
            }else if (cur==parent.left){
                parent.left=cur.left;
            }else {
                parent.right=cur.left;
            }
        }else {
            TreeNode targetParent=cur;
            TreeNode target=cur.right;
            while (target.left!=null){ //此时target为cur右树中最小的值
                targetParent=target;
                target=target.left;
            }
            cur.val=target.val;
            if (target==targetParent.left){
                targetParent.left=target.right;
            }else {
                targetParent.right=target.right;
            }

        }
    }

5. 性能分析

在这里插入图片描述

  • 最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:log2N(二叉树的高度)
  • 最差情况下,二叉搜索树退化为单支树,其平均比较次数为:N/2(最好情况第一个就查找,最坏情况最后一个才查找到 平均下来就是 N/2)

附:整体基本二叉搜索树实现代码

class TreeNode{
    public int val;
    public TreeNode left;
    public TreeNode right;
    public TreeNode(int val){
        this.val=val;
    }
}

public class BinarySearchTree {
    public TreeNode root=null;

    public TreeNode search(int key){
        TreeNode cur=root;
        while (cur!=null){
            if (cur.val<key){
                cur=cur.right;
            }else if (cur.val==key){
                return cur;
            }else {
                cur=cur.left;
            }
        }
           return null;
    }

    public boolean insert(int val){
        if (root==null){
            root=new TreeNode(val);
            return true;
        }
        TreeNode parent=null;
        TreeNode cur=root;
        while (cur!=null){
            if (cur.val<val){
                parent=cur;
                cur=cur.right;
            }else if (cur.val==val){
                return false;//不能有相同的数据
            }else {
                parent=cur;
                cur=cur.left;
            }
        }
        TreeNode node=new TreeNode(val);
        if (parent.val<val){
            parent.right=node;
        }else {
            parent.left=node;
        }
        return true;
    }

    public void remove(int key){
        TreeNode cur=root;
        TreeNode 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(TreeNode cur,TreeNode parent){
        if (cur.left==null){
            if (cur==root){
                root=cur.right;
            }else if (cur==parent.left){
                parent.left=cur.right;
            }else {
                parent.right=cur.right;
            }
        }else if (cur.right==null){
            if (cur==root){
                root=cur.left;
            }else if (cur==parent.left){
                parent.left=cur.left;
            }else {
                parent.right=cur.left;
            }
        }else {
            TreeNode targetParent=cur;
            TreeNode target=cur.right;
            while (target.left!=null){ //此时target为cur右树中最小的值
                targetParent=target;
                target=target.left;
            }
            cur.val=target.val;
            if (target==targetParent.left){
                targetParent.left=target.right;
            }else {
                targetParent.right=target.right;
            }

        }
    }

    //中序遍历
    public void inOrder(TreeNode root){
        if (root==null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }

    public static void main(String[] args) {
    //测试:
        int[] array = {10,8,19,3,9,4,7};
        BinarySearchTree binarySearchTree = new BinarySearchTree();
        for (int i = 0; i < array.length; i++) {
            binarySearchTree.insert(array[i]);
        }
        binarySearchTree.inOrder(binarySearchTree.root);
        System.out.println("插入重复的数据");
        System.out.println(binarySearchTree.insert(3));
        System.out.println("删除数据:");
        binarySearchTree.remove(7);
        System.out.println();
        binarySearchTree.inOrder(binarySearchTree.root);

    }

}

  • 7被成功删除,测试成功 !
    在这里插入图片描述

  • over ~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值