Java实现二叉查找树的增删查详解

 更新时间:2022年06月28日 11:30:33   作者:WX7251  
二叉查找树(ADT)是一个具有对于树种的某个节点X,它的左节点都比X小,它的右节点都比X大的二叉树。本文将用Java实现二叉查找树的增删查,需要的可以参考一下

定义

二叉查找树(ADT)是一个具有对于树种的某个节点X,它的左节点都比X小,它的右节点都比X大的二叉树。如下就是一个符合

要求的二叉查找树:

增加节点

1.定义节点类:

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

2.插入元素

我们采用递归的方法:

1.判断与根节点是否相同,相同无需操作

2.比根元素小往左边查找,左节点不存在的话则作为左节点插入即可

3.比根元素大往右边查找,右节点不存在的话则作为右节点插入即可

代码实现如下:

Node root;
 
    /**
     * 添加元素
     * @param val
     */
    public void add(int val){
        if(root==null){
            root=new Node(val);
            return;
        }
        addNode(val,root);
    }
    private void addNode(int val,Node root){
        if(root==null || root.val==val){
            return;
        }
        if(root.val>val){
            if(root.left==null){
                root.left=new Node(val);
            }else {
                addNode(val,root.left);
            }
        }else {
            if(root.right==null){
                root.right=new Node(val);
            }else {
                addNode(val,root.right);
            }
        }
    }

查询节点

我们采用递归的方法:

1.判断与根节点是否相同,相同则返回true

2.比根元素小往左边查找,左节点为null则返回false表示不存在

3.比根元素大往右边查找,右节点为null则返回false表示不存在

代码实现如下:

/**
     * 判断指定值是否存在
     * @param val 指定值
     * @return true--存在   false--不存在
     */
    public boolean findVale(int val){
        return isExit(root,val);
    }
 
    private boolean isExit(Node node,int val){
        if(node==null){
            return false;
        }
        if(node.val==val){
            return true;
        }else if(node.val>val){
            return isExit(node.left,val);
        }else {
            return isExit(node.right,val);
        }
    }

删除节点

删除元素时要判断元素的情况:

1.删除的元素没有叶子节点,直接删除,如删除值为1的节点,虽然平衡性不是太好,但是还是符合二叉查找树的特性

2.删除的元素只有一个节点,删除元素并将指针指向其子节点 ,如删除值为4的节点:

3.删除的元素有左右两个节点,从右节点中找出大于该节点的最小节点,作为新的节点A,如删除节点值为2的节点:

代码实现如下:

/**
     * 删除元素
     * 1.删除的元素没有叶子节点,直接删除
     * 2.删除的元素只有一个节点,删除元素并将指针指向其子节点
     * 3.删除的元素有两个节点,从右节点中找出大于该元素的最小值,作为新的节点
     * @param val
     */
    public void deleteElement(int val){
        deleteElement(null,root,val,true);
    }
 
    /**
     * 删除元素
     * @param prev 父节点
     * @param root 当前节点
     * @param val  删除值
     * @param isright  是否是右节点
     */
    private void deleteElement(Node prev,Node root,int val,boolean isright){
        if(root.val==val){
            //删除的元素没有叶子节点,直接删除
            if(root.left==null &&  root.right==null){
                changeValue(prev,null,isright);
            }else if(root.left!=null &&  root.right!=null){
                //3.删除的元素有两个节点,从右节点中找出大于该元素的最小值,作为新的节点
                changeValue(prev,new Node(findMinGt(root,root.right,true)),isright);
                if(prev==null){
                    //对于头结点的删除特殊处理
                    prev=this.root;
                    prev.left=root.left;
                    prev.right=root.right;
                    return;
                }
                if(isright){
                    prev.right.right=root.right;
                    prev.right.left=root.left;
                }else {
                    prev.left.right=root.right;
                    prev.left.left=root.left;
                }
            }//删除的元素只有一个节点,删除元素并将指针指向其子节点
            else if(root.left!=null){
                changeValue(prev,root.left,isright);
            }else {
                changeValue(prev,root.right,isright);
            }
            return;
        }
        if(root.val>val){
            deleteElement(root,root.left,val,false);
        }else{
            deleteElement(root,root.right,val,true);
        }
    }
    //改变元素值
    private void changeValue(Node prev,Node value,boolean isright){
        if(prev==null){
            root=value;
            return;
        }
        if(isright){
            prev.right=value;
        }else {
            prev.left=value;
        }
    }
    //寻找大于根节点的最小值
    private int findMinGt(Node prev,Node root,boolean isRight){
        if(root.left==null && root.right==null){
            changeValue(prev,null,isRight);
            return root.val;
        }
        if(root.left==null){
            changeValue(prev,null,isRight);
            return root.val;
        }
        return findMinGt(root,root.left,false);
    }

到此这篇关于Java实现二叉查找树的增删查详解的文章就介绍到这了,更多相关Java二叉查找树增删查内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring中Bean的单例和多例使用说明

    Spring中Bean的单例和多例使用说明

    这篇文章主要介绍了Spring中Bean的单例和多例使用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • mybatis使用resultMap获取不到值的解决方案

    mybatis使用resultMap获取不到值的解决方案

    这篇文章主要介绍了mybatis使用resultMap获取不到值的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 在Spring Boot中集成RabbitMQ详细步骤(最新推荐)

    在Spring Boot中集成RabbitMQ详细步骤(最新推荐)

    本文将介绍如何在Spring Boot项目中集成RabbitMQ,实现生产者和消费者的基本配置,本文分步骤给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-12-12
  • 浅谈java中异常抛出后代码是否会继续执行

    浅谈java中异常抛出后代码是否会继续执行

    这篇文章主要给大家介绍了java中异常抛出后代码是否会继续执行,文章通过几种情况的代码示例给大家详细分析了这个情况,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-10-10
  • 关于springboot 配置文件中属性变量引用方式@@解析

    关于springboot 配置文件中属性变量引用方式@@解析

    这篇文章主要介绍了关于springboot 配置文件中属性变量引用方式@@解析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • java如何删除非空文件夹

    java如何删除非空文件夹

    这篇文章主要介绍了java如何删除非空文件夹问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • java线程并发cyclicbarrier类使用示例

    java线程并发cyclicbarrier类使用示例

    CyclicBarrier类似于CountDownLatch也是个计数器,不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续,下面使用示例学习他的使用方法
    2014-01-01
  • SpringBoot整合Spring Security的详细教程

    SpringBoot整合Spring Security的详细教程

    这篇文章主要介绍了SpringBoot整合Spring Security的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Java 入门图形用户界面设计之单选按钮

    Java 入门图形用户界面设计之单选按钮

    图形界面(简称GUI)是指采用图形方式显示的计算机操作用户界面。与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受,本篇精讲Java语言中关于图形用户界面的单选按钮
    2022-02-02
  • 简单聊聊RabbitMQ中的队头阻塞问题

    简单聊聊RabbitMQ中的队头阻塞问题

    这篇文章主要为大家详细介绍了RabbitMQ中的队头阻塞问题以及相关的解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-02-02

最新评论