首页 > 编程语言 >【Java】二叉搜索树

【Java】二叉搜索树

时间:2024-03-23 15:30:26浏览次数:20  
标签:parent right Java cur val 二叉 搜索 left

文章目录


一、搜索树

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
它的左右子树也分别为二叉搜索树

在这里插入图片描述
仔细观察上图,可以发现二叉搜索树的一个特性:
中序遍历二叉搜索树是有序的,所以二叉搜索树也被称为二叉排序树

二、使用代码实现一棵二叉搜索树

1.查找

遍历这棵树,先从树的根节点开始查找,如果树的根节点是我们要查找的元素就返回根节点,如果要查找的元素比我们的根节点小,就去树的左边寻找,如果比我们的根节点大就去树的右边寻找,直到遍历完整棵树为止

代码如下:

    public boolean search(int val) {
        TreeNode cur = root;
        while (cur != null) {
            //左树中去找
            if(cur.val > val) {
                cur = cur.left;
            //右树中去找
            }else if(cur.val < val) {
                cur = cur.right;
            }else {
                return true;
            }
        }
        return false;
    }

2.插入

往二叉搜索树插入一个元素的时候,我们要注意两点,首先如果二叉搜索树为空,则直接令 root 为当前插入的节点即可,如果不为空,则新的元素会依次与节点比较,如果比根节点大,则去根的右边,比根节点小,则去根的左边
首先定义一个 cur 引用,当 cur 等于 null 了,则表示是我要插入的位置,找到了要插入的位置,我们还得知道这个位置的父亲节点是谁,通过父亲节点将元素插入到该二叉树中

代码如下:

    public void insert(int val) {
        if(root == null) {
            root = new TreeNode(val);
            return;
        }
        TreeNode cur = root;
        //记录cur的上一个节点
        TreeNode parent = null;
        while (cur != null) {
            if(cur.val < val) {
                parent = cur;
                cur = cur.right;
            }else if(cur.val > val) {
                parent = cur;
                cur = cur.left;
            }else {
                return;
            }
        }
        //cur为空 将val插入到parent的左树或者右树
        TreeNode node = new TreeNode(val);
        if(parent.val > val) {
            parent.left = node;
        }else {
            parent.right= node;
        }
    }

3.删除(重点)

二叉搜索树中删除一个元素是很麻烦的,我们要把每一种情况都列举出来,而且在删除完一个元素后还要满足二叉搜素树的性质
设 cur 为要删除的元素,parent为待删除结点的双亲结点为,首先我们要判断这个二叉搜索树中,是否存在要删除的节点,这个方法在上面已经写过了,找到要删除的节点后,再对每一种情况进行删除:

1.cur没有左子树
cur 是 root,则 root = cur.right
cur 不是 root,cur 是 parent.left,则 parent.left = cur.right
cur 不是 root,cur 是 parent.right,则 parent.right = cur.right
图解如下:
![在这里插入图片描述](/i/ll/?i=direct/d28ddf430aa74bb3bd781a311aae143b.pn
2.cur没有右子树
cur 是 root,则 root = cur.left
cur 不是 root,cur 是 parent.left,则 parent.left = cur.left
cur 不是 root,cur 是 parent.right,则 parent.right = cur.left
图解如下:
在这里插入图片描述
3.cur既有左子树又有右子树
使用替换法进行删除,即在 cur 的右子树中,一直往左寻找最小的元素,将这个最小值赋值给要删除节点的 val 值中,接着把这个最小元素的节点删除即可
图解如下:
在这里插入图片描述
在这里插入图片描述
代码如下:

    public void remove(int val) {
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null) {
            if(cur.val < val) {
                parent = cur;
                cur = cur.right;
            }else if(cur.val > val) {
                parent = cur;
                cur = cur.left;
            }else {
                removeNode(parent,cur);
                return;
            }
        }
    }
    private void removeNode(TreeNode parent,TreeNode cur) {
        //左树为空
        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 t = cur.right;
            TreeNode tp = cur;
            while (t.left != null) {
                tp = t;
                t = t.left;
            }
            cur.val = t.val;

            if(tp.left == t) {
                tp.left = t.right;
            }else {
                tp.right = t.right;
            }
        }
    }

总结

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。
对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多
二叉搜索树在最好的情况下为完全二叉树,查找的平均比较次数为:logn
二叉搜索树在最差的情况下退化成单分支,查找的平均比较次数为:n/2
注意:
二叉搜索树不要求是完全二叉树或满二叉树,甚至会出现单分支的二叉搜索树,所以针对这种特殊的情况进行了优化也就延申出了 AVL树,当发现二叉搜索树左右子树高度差太大,会自动旋转,以致平衡,避免旋转的次数太多,又引入了红黑树,给节点增加了颜色,细节部分后期讲解,这里有个概念即可

标签:parent,right,Java,cur,val,二叉,搜索,left
From: https://blog.csdn.net/2301_78373304/article/details/136949934

相关文章

  • 【附源码】JAVA计算机毕业设计音乐平台设计与实现(springboot+mysql+开题+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展,互联网已经渗透到人们生活的方方面面,音乐作为人们日常生活的重要娱乐方式,其在线化、平台化的发展趋势日益明显。近年来,音乐平......
  • 【附源码】JAVA计算机毕业设计音乐平台的设计(springboot+mysql+开题+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着数字技术的迅猛发展,音乐产业正在经历一场深刻的变革。传统音乐销售模式逐渐式微,而在线音乐平台以其便捷性、多样性和互动性,迅速占领了市场。当前......
  • Java程序设计基础 第一章:Java的历史、环境搭建
        Java是一种计算机编程语言;除了java还有很多编程语言:c语言、c++、c#、python等,不同的计算机编程语言语法不同;应用场景不同;                                                 java是一种后端开发编程语言一、......
  • JAVA循环语句
    循环语句分为while,dowhile,forwhile语法:while(条件表达式){        //语句块;}符合条件,循环继续执行,否则,循环退出特点:先判断再执行只要条件表达式为true,循环体会一直执行下去示例:publicclassMain{publicstaticvoidmain(Stringargs[]){int......
  • 一道平衡二叉树的求解
    最近在看二叉树的算法,我觉得有点迷迷糊糊,就是那种一看就会,一写就费。我有点很奇怪的感觉,就感觉二叉树的很多问题,其实在于一步一步的遍历(或者称为迭代,或者是递归方法),然后在遍历的基础上进行逻辑(业务)操作。首先在这讲一下递归。递归有三部曲:一.确定函数参数,确定函数的返回值......
  • JAVA阻塞IO(BIO)简介
    一、BIO编程传统的BIO编程网络编程的基本模型是C/S模型,即两个进程间的通信。服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信。传统的同步阻塞模型开发中,ServerSocket负责绑定IP地址,启......
  • JavaScript高级(十)----JavaScript中的类【重述原型链】!
     类在JavaScript其实本来没有类的概念,哪怕是ES5以后的class,严格意义上来说也只是构造函数的语法糖,之所以喜欢称之为类,因为JavaScript也可以面向对象开发。类的声明classPerson{}functionPerson1(){}//上面两种写法本质上是一样的console.log(typeofPerson)cons......
  • JavaScript高级(九)---JavaScript的六种继承方式
    1、原型继承实现:1234567functionSuper(){this.a=1}Super.prototype.say=function(){console.log(‘hhh')}functionSub(){}Sub.prototype=newSuper()consttest=newSub()console.log(test.say())//hhh优点:通过原型继承多个引用类型的属性和......
  • JavaWeb学习笔记——第二天
    JavaScript什么是JavaScriptJavaScript(简称:JS)是一门跨平台、面向对象的脚本语言。是用来控制网页行为的,它能使网页可交互。JavaScript和Java是完全不同的语言,不论是概念还是设计都不一样。但是基础语法类似。JavaScript在1995年由BrendanEich发明,并于1997年成为......
  • 【Java - 框架 - HttpClient】(01) 使用“HttpClient“爬取网页的代码示例 - 快速上手
    使用"HttpClient"爬取网页的代码示例-快速上手;依赖<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.14</version></dependency><dependency>......