二叉搜索树的简单理解

1. 二叉搜索树

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

若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

它的左右子树也分别为二叉搜索树

如下图所示,就是一个简单的二叉搜索树,且存储的数据为:

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

2. 二叉搜索树的实现

2.1 二叉搜索树的创建

简单创建一个二叉树;

java 复制代码
package binarysearchtree;

public class BinarySearchTree0 {
    static class TreeNode{
        public int value;
        public TreeNode left;
        public TreeNode right;

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

2.2 查找关键字key

思路如下:

1、若根节点不为空:

1.1如果根节点value==查找key,返回true

1.2如果根节点value > 查找key,在其左子树查找

1.3如果根节点value< 查找key,在其右子树查找,如果找不到,返回false

2、如果根节点为空,则返回false;以下为分析图解:

代码实现:

java 复制代码
 public TreeNode root ;//根节点
    public boolean findKey(int key){
        TreeNode cur = root;
        while (cur != null){
            if (cur.value == key){
                return true;
            }else if (key > cur.value){
                cur = cur.right;
            }else {
                cur = cur.left;
            }
        }
            return false;
    }

2.3 插入关键字key的节点

思路:

插入操作可以分为以下两种情况:

  1. 如果树为空树,即根 == null,直接插入

2.如果树不是空树,按照查找逻辑确定插入位置,插入新结点

下图举个例子来分析:

总体分析:

1、先确定节点左右移动的方向

  • 如果节点root.value==key,该值在搜索数中已经存在,无需插入,return flase;
  • 如果节点root.value>key,在其左子树找合适位置
  • 如果节点root.value<key,在其右子树找合适位置

2、引入parent,该节点定义为与key值最后比较之后,接下来要进行插入节点操作的节点;

  • 如果节点parrent.value>key,新建key节点插在parent的左边
  • 如果节点parrent.value<key,新建key节点插在parent的右边

代码如下图所示:

java 复制代码
  public void insertkey(int key) {
        if(root == null) {
            root = new TreeNode(key);
            return;
        }
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null) {
            if (key == cur.value) {
                return ;
            } else if (key < cur.value) {
                parent = cur;
                cur = cur.left;
            } else {
                parent = cur;
                cur = cur.right;
            }
        }
        TreeNode node = new TreeNode(key);
        if (key < parent.value) {
            parent.left = node;
        } else {
            parent.right = node;
        }
    }

2.4删除关键字key

假设要删除的结点为 cur, 待删除结点的双亲结点为 parent,我们分以下四种情况来分析:

1. cur.left == null

1.1 cur 是 root ,则 root = cur.right(图解如下)

1.2 cur 不是 root,cur 是 parent.left,则 parent.left = cur.right

1.3 cur 不是 root,cur 是 parent.right,则 parent.right = cur.right

  1. cur.right == null(下面的三种情况与1截然相反,此处略)

2.1 cur 是 root ,则 root = cur.left
2.2 cur 不是 root , cur 是 parent.left ,则 parent.left = cur.left
2.3 cur 不是 root , cur 是 parent.right ,则 parent.right = cur.left

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

思路:

我们使用target来遍历寻找子树中关键节点,targetParent用来记录target的父亲节点

找到相应节点后与待删除的cur节点的值进行替换,最后删除target结点即可

详细的图解思路如下所示:

4.cur左右孩子均不存在

直接置为null;

综上所述,代码实现:

java 复制代码
    public void remove(int val) {
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null) {
            if (val == cur.val) {
                removeNode(parent, cur);
                break;
            } else if (val < cur.val) {
                parent = cur;
                cur = cur.left;
            } else {
                parent = cur;
                cur = cur.right;
            }
        }
    }
 
    private void removeNode(TreeNode parent, TreeNode cur) {
        if (cur.left==null){
            if(cur==root){
                root=cur.right;
            }else if(parent.left==cur){
                parent.left=cur.right;
            }else{
                parent.right=cur.right;
            }
        } else if (cur.right==null) {
            if(cur==root){
                root=cur.left;
            }else if(parent.left==cur){
                parent.left=cur.left;
            }else{
                parent.right=cur.left;
            }
        }else{
            TreeNode target = cur.right;
            TreeNode targetParent = cur;
            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. 二叉搜索树性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。

但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:log (2^n)

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

ps:二叉搜索树的内容就到这里了,大家喜欢的话就请一键三连哦!!!

相关推荐
鲁子狄26 分钟前
[笔记] 使用 Jenkins 实现 CI/CD :从 GitLab 拉取 Java 项目并部署至 Windows Server
java·windows·笔记·ci/cd·ssh·gitlab·jenkins
IT古董1 小时前
【权限管理】Apache Shiro学习教程
java·apache·shiro·权限
风月歌1 小时前
基于Spring Boot的海滨体育馆管理系统的设计与实现
java·spring boot·后端
ggdpzhk5 小时前
idea 编辑竖列:alt +shift+insert
java·ide·intellij-idea
hikktn6 小时前
Java 兼容读取WPS和Office图片,结合EasyExcel读取单元格信息
java·开发语言·wps
迪迦不喝可乐6 小时前
软考 高级 架构师 第十一章 面向对象分析 设计模式
java·设计模式
檀越剑指大厂6 小时前
【Java基础】使用Apache POI和Spring Boot实现Excel文件上传和解析功能
java·spring boot·apache
苹果酱05676 小时前
Golang的网络流量分配策略
java·spring boot·毕业设计·layui·课程设计
孑么7 小时前
GDPU Android移动应用 重点习题集
android·xml·java·okhttp·kotlin·android studio·webview
Felix_12157 小时前
2025 西电软工数据结构机考 Tip (By Felix)
算法