Java实现二分搜索树的示例代码


Posted in Java/Android onMarch 17, 2022

1.概念

a.是个二叉树(每个节点最多有两个子节点)

b.对于这棵树中的节点的节点值

左子树中的所有节点值 < 根节点 < 右子树的所有节点值

二分搜索树中一般不考虑值相等的情况(元素不重复)JDK中的搜索树就不存在相同的值(TreeMap-key)

Java实现二分搜索树的示例代码

最大特点:也是判断是否是搜索树的方法

对该树进行中序遍历,就可以得到一个升序集合0 1 2 3 4 5 6 7 8 9

在一个有序区间上进行二分查找的时间复杂度? logn不断将集合/2/2 / 2 ==1为止logN

logN =》联想到"树"

2.重点操作

Java实现二分搜索树的示例代码

当删除58时,此节点左右子树都不为空

Hibbard Deletion 1962

在BST中删除一个左右子树都存在的节点

找到当前以58为根节点的前驱或者后继节点作为删除后的新节点

前驱:在以58为根的BST中最后一个小于58的节点->53

后继:在以58为根的BST中第一个大于58的节点->59

当我们使用后继节点时,先连removeMin(root.right),在连root.left

TreeNode successor = findMin(root.right);
successor.right = removeMin(root.right);
successor.left = root.left;

3.完整代码

import java.util.NoSuchElementException;
 
/**
 * 基于整型的
 * 普通的二分搜索树
 */
public class BST {
 
    private class TreeNode{
        private int val;
        private TreeNode left;
        private TreeNode right;
 
        public TreeNode(int val) {
            this.val = val;
        }
    }
 
    private int size;
    private TreeNode root;
 
    /**
     * 向以root为根的BST中插入一个新的结点val
     * @param val
     */
    public void add(int val){
        root = add(root,val);
    }
 
    private TreeNode add(TreeNode root, int val) {
        if(root == null){
            //创建一个新节点
            TreeNode newNode = new TreeNode(val);
            size++;
            return newNode;
        }
        //左子树插入
        if(val < root.val){
            root.left = add(root.left,val);
        }
        //右子树插入
        if(val > root.val){
            root.right = add(root.right,val);
        }
        return root;
    }
 
    /**
     * 判断当前以root为根的BST中是否包含了val
     * @param val
     * @return
     */
    public boolean contains(int val){
        return contains(root,val);
    }
 
    private boolean contains(TreeNode root, int val) {
        if(root == null){
            return false;
        }
        if(val == root.val){
            //找到了
            return true;
        }else if(val < root.val){
            //递归左子树查找
            return contains(root.left,val);
        }else{
            //递归右子树查找
            return contains(root.right,val);
        }
    }
 
    /**
     * 找到最小值
     * @return
     */
    public int findMin(){
        //判空
        if(root == null){
            //抛出一个空指针异常
            throw new NoSuchElementException("root is empty! cannot find min");
        }
        TreeNode minNode = findMin(root);
        return minNode.val;
    }
 
    private TreeNode findMin(TreeNode root) {
        //当此节点左子树为空,说明此节点是最小值
        if(root.left == null){
            return root;
        }
        //递归访问左子树
        return findMin(root.left);
    }
 
    /**
     * 找到最大值
     * @return
     */
    public int findMax(){
        //判空
        if(root == null){
            throw new NoSuchElementException("root is empty! cannot find max");
        }
        TreeNode maxNode = findMax(root);
        return maxNode.val;
    }
 
    private TreeNode findMax(TreeNode root) {
        //当此节点右子树为空,说明此节点是最大值
        if(root.right == null){
            return root;
        }
        //递归访问右子树
        return findMax(root.right);
    }
 
    /**
     * 在当前BST中删除最小值节点,返回删除的最小值
     * @return
     */
    public int removeMin(){
        int min =findMin();
        root = removeMin(root);
        return min;
    }
 
    private TreeNode removeMin(TreeNode root) {
        if(root.left == null){
            TreeNode right = root.right;
            //找到最小值,删除节点
            root = root.left = null;
            size--;
            return right;
        }
        root.left = removeMin(root.left);
        return root;
    }
 
    /**
     * 在当前BST中删除最大值节点,返回删除的最大值
     * @return
     */
    public int removeMax(){
        int max = findMax();
        root = removeMax(root);
        return max;
    }
 
    //在当前以root为根的BST中删除最小值所在的节点,返回删除后的树根
    private TreeNode removeMax(TreeNode root) {
        if(root.right == null){
            TreeNode right = root.right;
            //找到最大值,删除节点
            root = root.right = null;
            size--;
            return right;
        }
        root.right = findMax(root.right);
        return root;
    }
 
    /**
     * 在当前以root为根节点的BST中删除值为val的节点
     * 返回删除后的新的根节点
     * @return
     */
    public void removeValue(int value){
        root = removeValue(root,value);
    }
 
    private TreeNode removeValue(TreeNode root, int value) {
        if(root == null){
            throw new NoSuchElementException("root is empty! cannot find remove");
        }else if(value < root.val){
            root.left = removeValue(root.left,value);
            return root;
        }else if(value > root.val){
            root.right = removeValue(root.right,value);
            return root;
        }else {
            //此时value == root.value
            if(root.left == null){
                //删除最小数
                TreeNode right = root.right;
                root = root.right = null;
                size--;
                return right;
            }
            if(root.right == null){
                //删除最大数
                TreeNode left = root.left;
                root = root.left =null;
                size--;
                return left;
            }
            //找到当前该删除节点的前驱或者后继节点作为删除后的新节点
            //当我们使用后继节点时,先连removeMin(root.right),在连root.left
            TreeNode successor = findMin(root.right);
            successor.right = removeMin(root.right);
            successor.left = root.left;
            return successor;
        }
    }
 
 
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        generateBSTString(root,0,sb);
        return sb.toString();
    }
 
    //直观打印,可以看到树的深度
    private void generateBSTString(TreeNode root, int height, StringBuilder sb) {
        if(root == null){
            sb.append(generateHeightString(height)).append("NULL\n");
            return;
        }
        sb.append(generateHeightString(height)).append(root.val).append("\n");
        generateBSTString(root.left,height+1,sb);
        generateBSTString(root.right,height+1,sb);
    }
 
    private String generateHeightString(int height) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < height; i++) {
            sb.append("--");
        }
        return sb.toString();
    }
}

到此这篇关于Java实现二分搜索树的示例代码的文章就介绍到这了,更多相关Java二分搜索树内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Java/Android 相关文章推荐
Java实战之用Swing实现通讯录管理系统
Jun 13 Java/Android
详解Java实践之建造者模式
Jun 18 Java/Android
Java中常用解析工具jackson及fastjson的使用
Jun 28 Java/Android
详解Java ES多节点任务的高效分发与收集实现
Jun 30 Java/Android
SpringBoot集成Druid连接池连接MySQL8.0.11
Jul 02 Java/Android
Java Spring 控制反转(IOC)容器详解
Oct 05 Java/Android
java多态注意项小结
Oct 16 Java/Android
Spring Data JPA框架自定义Repository接口
Apr 28 Java/Android
Java 多线程并发FutureTask
Jun 28 Java/Android
SpringBoot接入钉钉自定义机器人预警通知
Jul 15 Java/Android
spring 项目实现限流方法示例
Jul 15 Java/Android
阿里面试Nacos配置中心交互模型是push还是pull原理解析
Jul 23 Java/Android
使用HttpSessionListener监听器实战
Mar 17 #Java/Android
spring cloud eureka 服务启动失败的原因分析及解决方法
Mar 17 #Java/Android
Java基于Dijkstra算法实现校园导游程序
Java中的随机数Random
Mar 17 #Java/Android
SpringBoot中HttpSessionListener的简单使用方式
Mar 17 #Java/Android
SpringBoot+Redis实现布隆过滤器的示例代码
Mar 17 #Java/Android
Java9新特性对HTTP2协议支持与非阻塞HTTP API
You might like
mysql5的sql文件导入到mysql4的方法
2008/10/19 PHP
PHP优于Node.js的五大理由分享
2012/09/15 PHP
基于php验证码函数的使用示例
2013/05/03 PHP
tp5 sum某个字段相加得到总数的例子
2019/10/18 PHP
Javascript获取HTML静态页面参数传递值示例
2013/08/18 Javascript
Knockout数组(observable)使用详解示例
2013/11/15 Javascript
JS实现的生成随机数的4个函数分享
2015/02/11 Javascript
JS中的Replace方法使用经验分享
2015/05/20 Javascript
JavaScript和HTML DOM的区别与联系及Javascript和DOM的关系
2015/11/15 Javascript
jQuery zTree加载树形菜单功能
2016/02/25 Javascript
javascript基础知识
2016/06/07 Javascript
js严格模式总结(分享)
2016/08/22 Javascript
D3.js实现直方图的方法详解
2016/09/25 Javascript
jquery实现手机端单店铺购物车结算删除功能
2017/02/22 Javascript
详解如何在angular2中获取节点
2017/11/23 Javascript
JavaScript+H5实现微信摇一摇功能
2018/05/23 Javascript
详解使用element-ui table组件的筛选功能的一个小坑
2018/11/02 Javascript
利用Angular7开发一个Radio组件的全过程
2019/07/11 Javascript
typescript nodejs 依赖注入实现方法代码详解
2019/07/21 NodeJs
详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑
2019/09/17 Javascript
vue实现表格过滤功能
2019/09/27 Javascript
Python3实现监控新型冠状病毒肺炎疫情的示例代码
2020/02/13 Python
scrapy数据存储在mysql数据库的两种方式(同步和异步)
2020/02/18 Python
详解python中groupby函数通俗易懂
2020/05/14 Python
MoviePy简介及Python视频剪辑自动化
2020/12/18 Python
HTML5新增属性data-*和js/jquery之间的交互及注意事项
2017/08/08 HTML / CSS
StubHub哥伦比亚:购买和出售您的门票
2016/10/20 全球购物
Godiva巧克力英国官网:比利时歌帝梵巧克力
2018/08/28 全球购物
波兰品牌鞋履在线商店:Eastend.pl
2020/01/11 全球购物
质检部岗位职责
2013/11/11 职场文书
员工薪酬激励方案
2014/06/13 职场文书
2014老师三严三实对照检查材料思想汇报
2014/09/18 职场文书
单位作风建设剖析材料
2014/10/11 职场文书
部门优秀员工推荐信
2015/03/24 职场文书
《平行四边形的面积》教学反思
2016/02/16 职场文书
在NumPy中深拷贝和浅拷贝相关操作的定义和背后的原理
2022/04/14 Python