二叉平衡树之二叉树搜索树【咱们一起手动模拟实现】

目录

1、什么是二叉搜索树?

2、手动模拟二叉搜索树

2.1、整体代码 

2.2、查找数据

2.3、插入数据 

2.4、删除数据

3、性能分析


1、什么是二叉搜索树?

二叉搜索树也叫作二叉排序树,可以使一颗空树,也可以是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树的所节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树的所节点的值都大于根节点的值
  • 它的左右子树也分别是二叉搜索树

举例:


2、手动模拟二叉搜索树

2.1、整体代码 


public class BinarySearchTree {

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

        public TreeNode(int val) {
            this.val = val;
        }
    }
    //搜索树的根
    public TreeNode root;

    /**
     * 查找key是否存在于二叉搜索树当中
     * @param key
     * @return 当前节点找到返回地址,否则返回null
     */
    public TreeNode search(int key) {
        


    }

    /**
     * 插入节点
     * @param key
     */
    public boolean insert(int key) {
     



    }

     /**
     * 删除节点
     * @param key
     */
    public void remove(int key) {
       


    }
}

2.2、查找数据

代码:

      /**
     * 查找key是否存在于二叉搜索树当中
     * @param key
     * @return 当前节点找到返回地址,否则返回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.3、插入数据 

  • 树为空,直接插入
  • 树不为空,按照查找逻辑确定插入位置,如下: 

代码:

   /**
     * 插入节点
     * @param key
     */
    public boolean insert(int key) {
        TreeNode node = new TreeNode(key);
        if(root == null) {
            root = node;
            return true;
        }
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null) {
            if(cur.val < key) {
                parent = cur;
                cur = cur.right;
            } else if(cur.val > key) {
                parent = cur;
                cur = cur.left;
            } else {
                //相等,搜索树中,无法存放值相等的节点
                return false;
            }
        }
        //cur == null
        if(key > parent.val) {
            parent.right = node;
        } else {
            parent.left = node;
        }
        return true;
    }

2.4、删除数据

设待删除结点为 cur, 待删除结点的双亲结点为 parent
1. cur.left == null
  •  cur root,则 root = cur.right
  •  cur 不是 rootcur parent.left,则 parent.left = cur.right
  •  cur 不是 rootcur parent.right,则 parent.right = cur.right
2. cur.right == null
  •  cur root,则 root = cur.left
  •  cur 不是 rootcur parent.left,则 parent.left = cur.left
  •  cur 不是 rootcur parent.right,则 parent.right = cur.left
3. cur.left != null && cur.right != null
  • 需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题

代码: 

    /**
     * 删除节点
     * @param key
     */
    public void remove(int key) {
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null) {
            if(cur.val < key) {
                parent = cur;
                cur = cur.right;
            } else if(cur.val > key) {
                cur = cur.left;
            } else {
                //该节点需要删除
                //1、cur.left == null
                if(cur.left == null) {
                    if(cur == root) {
                        root = cur.right;
                    } else if(cur == parent.left) {
                        parent.left = cur.right;
                    } else {
                        parent.right = cur.right;
                    }

                }//2、cur.right = null
                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;
                    }
                }
                //3、cur.left != null && cur.right != null
                else {
                    TreeNode targetParent = cur;
                    TreeNode target = cur.right;
                    //替换时,可以找左子树的最大值,也可以是右子树的最小值
                    //我这里是,左子树的最大值
                    while (target.left != null) {
                        targetParent = target;
                        target = target.left;
                    }
                    cur.val = target.val;

                    if(targetParent.left == target) {
                        targetParent.left = target.right;
                    } else {
                        targetParent.right = target.right;
                    }
                }
            }
        }
    }

3、性能分析

  • 插入操作和删除操作都会必须先查找,查找效率代表了二叉搜索树中各个操作的性能
  • 在二叉搜索树中,如果每个元素查找的概率相等,则二叉搜索树平均查找的长度是结点在二叉搜索树的深度的函数,即节点越多,比较的次数越多
  • 对于同一个关键码集合,若插入次序不同,就可能会得到结构不同的二叉搜索树,如下:

这时,最优情况下,二叉搜索树为完全二叉树,平均比较次数为logN

最差情况下,二叉搜索树退化为单支树,平均比较次数为N/2

好啦,我们下期见咯~~~【AVL树】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

龙洋静

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

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

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

打赏作者

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

抵扣说明:

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

余额充值