Java数据结构-二叉搜索树

1. 概念

二叉搜索树是特殊的二叉树,也叫二叉排序树,它的特点是:每个结点的左子树上的所有结点的值都小于这个结点的值,右子树上的所有结点的值都大于这个结点的值,另外所有的左子树和右子树也分别为二叉搜索树,如图:
在这里插入图片描述

2. 二叉搜索树的操作

2.1 查找

根据二叉搜索树的性质来,很容易可以理解查找的逻辑:从根结点开始,比较结点的值与待查找的值,如果待查找的值比根结点的值小,说明待查找的结点一定在树的左边,如图
在这里插入图片描述
当然也有其他情况:根结点为空、该树不存在要查找的这个结点,这个时候直接返回null就可以了

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

2.2 插入

插入的前提:插入一定是在叶子结点上插入,因为插入之后也要满足二叉搜索树的性质,插入之前需要查找要插入的位置,而查找的逻辑和刚才的逻辑一样
在这里插入图片描述

2.3 删除

删除的情况比较复杂,主要分为以下情况(假设del为要删除的结点,parent为del的父亲结点):

1、cur.left == null

  • 1、del 是root
  • 2、del 不是root,del是parent.left
  • 3、del 不是root,del是parent.right

2、cur.right == null

  • 1、del 是root
  • 2、del 不是root,del是parent.left
  • 3、del 不是root,del是parent.right

3、cur.left != null && cur.right != null

下面我们一个一个分析
情况1:del.left==null

  • 情况1.1:del是根结点root,删除逻辑:root =del.right
    在这里插入图片描述

  • 情况1.2 :del不是根结点,del是parent.left删除逻辑:parent.left=del.right
    在这里插入图片描述

  • 情况1.3:del不是根结点,del是parent.right,删除逻辑:parent.right=del.right
    在这里插入图片描述
    情况2:del.right==null

  • 情况2.1:del是根结点root,删除逻辑root = del.left
    在这里插入图片描述

  • 情况2.2:del不是根结点,del是parent.left,删除逻辑:parent.left = del.left
    在这里插入图片描述

  • 情况2.3:del不是根结点,del是parent.right,删除逻辑:parent.right = del.left
    在这里插入图片描述
    情况3:要删除的结点左右都不为空
    如图
    在这里插入图片描述

两种方法:
1.找到del的左树找值最大的结点,将del结点的值替换成这个值,接着删除这个最大值的结点,如上图的37,删除之后的情况如下
在这里插入图片描述

2.找到del的右子树找值最小的结点,将del结点的值替换成这个值,接着删除这个最小值的结点,如上图的45,删除之后的结果如下
在这里插入图片描述

3. 全部代码

public class BinarySearchTree {
    static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

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

    public TreeNode root;


    /**
     * 查找
     *
     * @return
     */
    public TreeNode find(int key) {
        TreeNode cur = root;
        while (cur != null) {
            if (cur.val > key) {
                cur = cur.left;
            } else if (cur.val < key) {
                cur = cur.right;
            } else {
                return cur;
            }
        }
        return null;
    }

    //插入
    public void insert(int key) {
        TreeNode cur = root;
        TreeNode parent = null;
        TreeNode newNode = new TreeNode(key);
        if (cur == null) {
            root = newNode;
            return;
        }
        while (cur != null) {
            if (cur.val > key) {
                parent = cur;
                cur = cur.left;
            } else if (cur.val < key) {
                parent = cur;
                cur = cur.right;
            } else {
                return;
            }
        }
        if (parent.val > key) {
            parent.left = newNode;
        } else {
            parent.right = newNode;
        }
    }

    //删除
    public void delete(int key) {
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null) {
            if (key > cur.val) {
                parent = cur;
                cur = cur.right;
            } else if (key < cur.val) {
                parent = cur;
                cur = cur.left;
            } else {
                //删除结点
                remove(parent, cur);
                return;
            }
        }
    }

    // 分情况讨论
    private void remove(TreeNode parent, TreeNode del) {
        //情况1:del.left==null
        if (del.left == null) {
            //情况1.1 del是root
            if (del == root) {
                root = del.right;
            } else {
                if (del == parent.left) {
                    //情况1.2 del不是root,del是parent.left
                    parent.left = del.right;
                } else if (del == parent.right) {
                    //情况1.3 del不是root,del是parent.right
                    parent.right = del.right;
                }
            }
        } else if (del.right == null) {
            //情况2:del.right==null
            if (del == root) {
                //情况2.1 del是root
                root = del.left;
            } else {
                if (del == parent.left) {
                    //情况2.2 del是parent.left
                    parent.left = del.left;
                } else if (del == parent.right) {
                    //情况2.3 del是parent.right
                    parent.right = del.left;
                }
            }
        } else {
            //情况3 del.left和del.right都不为空
            //将del右树的值最小的结点或者左树的值最大的结点和del替换
            //右边找
            TreeNode target = del.right;
            TreeNode targetP = del;
            while (target.left != null) {
                targetP = target;
                target = target.left;
            }
            //删除之前先交换
            del.val = target.val;
            //分情况删除
            if (target == targetP.right) {
                targetP.right = target.right;
            }
            if (target == targetP.left) {
                targetP.left = target.right;
            }
        }
    }
}

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值