JavaSE 搜索树

news2024/9/24 20:02:57

目录

  • 1 概念
  • 2 操作
    • 2.1 查找
    • 2.2 插入
    • 2.3 删除
  • 3 性能分析
  • 4 和 java 类集的关系

1 概念

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

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值;
  2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
  3. 它的左右子树也分别为二叉搜索树

你会发现它中序遍历的结果就是有序的。
如下图所示就是一颗二叉搜索树:
在这里插入图片描述

2 操作

2.1 查找

在这里插入图片描述
具体实现代码示例如下所示:

package bstree;

class BinarySearchTree{
    static class BSNode{
        public int val;
        public BSNode left;
        public BSNode right;

        public BSNode(int val) {
            this.val = val;
        }}

    public BSNode root = null;

    public BSNode search(int val){
            if(root == null) return null;
            BSNode cur = root;
            while (cur != null){
            if(cur.val == val){
                return cur;
            }else if(cur.val > val){
                cur = cur.left;
            }else{
                cur = cur.right;
            }
        }
            return null;
        }
    }

public class TestDemo {
    public static void main(String[] args) {
   
}
}

2.2 插入

  1. 如果树为空树,即根 == null,直接插入。
    在这里插入图片描述
  2. 如果树不是空树,按照查找逻辑确定插入位置,插入新结点。
    在这里插入图片描述
    具体实现代码示例如下所示:
package bstree;

class BinarySearchTree{
    static class BSNode{
        public int val;
        public BSNode left;
        public BSNode right;

        public BSNode(int val) {
            this.val = val;
        }}

    public BSNode root = null;

    public BSNode search(int val){
            if(root == null) return null;
            BSNode cur = root;
            while (cur != null){
            if(cur.val == val){
                return cur;
            }else if(cur.val > val){
                cur = cur.left;
            }else{
                cur = cur.right;
            }
        }
            return null;
        }

    public boolean insert(int val){
            BSNode bsNode = new BSNode(val);
            if(root == null){
                root = bsNode;
                return true;
            }
            BSNode cur = root;
            BSNode parent = null;
            while(cur != null){
                if(cur.val == val){
                    return false;
                }else if(cur.val > val){
                    parent = cur;
                    cur = cur.left;
                }else{
                    parent = cur;
                    cur = cur.right;
                }
            }
            if(parent.val < val){
                parent.right = bsNode;
            }else{
                parent.left = bsNode;
            }
            return true;
        }
    }

public class TestDemo {
    public static void preOrder(BinarySearchTree.BSNode root){
        if(root == null){
            return;
        }
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }

    public static void inOrder(BinarySearchTree.BSNode root){
        if(root == null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }
    public static void main(String[] args) {
        BinarySearchTree binarySearchTree = new BinarySearchTree();
        binarySearchTree.insert(4);
        binarySearchTree.insert(3);
        binarySearchTree.insert(1);
        binarySearchTree.insert(15);
        binarySearchTree.insert(11);

        preOrder(binarySearchTree.root);
        System.out.println();
        inOrder(binarySearchTree.root);
        System.out.println();

        try {
            BinarySearchTree.BSNode ret = binarySearchTree.search(4);
            System.out.println(ret.val);
        }catch (NullPointerException e){
            System.out.println("没有找到当前的节点..........");
            e.printStackTrace();
        }
    }
}

2.3 删除

前提是删除这个节点之后,整棵树还是一棵二叉搜索树。
删除思路:
设待删除结点为 cur, 待删除结点的双亲结点为 parent。
则分为下面三种情况:

  1. cur.left == null

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

  1. cur.right == null

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

  1. cur.left != null && cur.right != null
  1. 如果像原来那样删除,那么一个节点就会出现两个父亲节点?
    需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键值最小),用它的值填补到被删除节点中,再来处理该结点的删除问题。
  2. 我们怎么知道放谁上去?
    当前需要删除的节点的左边找最大的,右边找最小的。

具体实现代码示例如下所示:

package bstree;

class BinarySearchTree {
    static class BSNode {
        public int val;
        public BSNode left;
        public BSNode right;

        public BSNode(int val) {
            this.val = val;
        }
    }

    public BSNode root = null;

    public BSNode search(int val) {
        if (root == null) return null;
        BSNode cur = root;
        while (cur != null) {
            if (cur.val == val) {
                return cur;
            } else if (cur.val > val) {
                cur = cur.left;
            } else {
                cur = cur.right;
            }
        }
        return null;
    }

    public boolean insert(int val) {
        BSNode bsNode = new BSNode(val);
        if (root == null) {
            root = bsNode;
            return true;
        }
        BSNode cur = root;
        BSNode parent = null;
        while (cur != null) {
            if (cur.val == val) {
                return false;
            } else if (cur.val > val) {
                parent = cur;
                cur = cur.left;
            } else {
                parent = cur;
                cur = cur.right;
            }
        }
        if (parent.val < val) {
            parent.right = bsNode;
        } else {
            parent.left = bsNode;
        }
        return true;
    }

    public void remove(int val) {
        if (root == null) return;
        BSNode cur = root;
        BSNode parent = null;
        while(cur !=null){
            if (cur.val == val) {
                removeNode(parent,cur,val);
            } else if (cur.val < val) {
                parent = cur;
                cur = cur.right;
            } else {
                parent = cur;
                cur = cur.left;
            }
        }}

        public void removeNode(BSNode parent,BSNode cur,int val){
            if(cur.left == null){
                if(cur == root){
                    root = cur.right;
                }else if(parent.left == cur){
                    parent.left = cur.right;
                }else if(parent.right == cur){
                    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 if(parent.right == cur){
                    parent.right = cur.left;
                }
            }else{
                //这里采取的是右边找最小的方法
                BSNode targetParent = cur;
                BSNode target = cur.right;

                while(target.left != null){
                    targetParent = target;
                    target = target.left;
                }
                //target指向的节点就是 右边的最小值
                cur.val = target.val;
                if(target == targetParent.left){
                    targetParent.left = target.right;
                }else{
                    targetParent.right = target.right;
                }
            }
        }
    }


public class TestDemo {
    public static void preOrder(BinarySearchTree.BSNode root){
        if(root == null){
            return;
        }
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }

    public static void inOrder(BinarySearchTree.BSNode root){
        if(root == null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }
    public static void main(String[] args) {
        BinarySearchTree binarySearchTree = new BinarySearchTree();
        binarySearchTree.insert(4);
        binarySearchTree.insert(3);
        binarySearchTree.insert(1);
        binarySearchTree.insert(15);
        binarySearchTree.insert(11);

        preOrder(binarySearchTree.root);
        System.out.println();
        inOrder(binarySearchTree.root);
        System.out.println();

        binarySearchTree.remove(15);
        System.out.println("=============删除===============");
        preOrder(binarySearchTree.root);
        System.out.println();
        inOrder(binarySearchTree.root);
        System.out.println();


        try {
            BinarySearchTree.BSNode ret = binarySearchTree.search(4);
            System.out.println(ret.val);
        }catch (NullPointerException e){
            System.out.println("没有找到当前的节点..........");
            e.printStackTrace();
        }
    }
}

3 性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。
对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:
在这里插入图片描述
最优情况下: 二叉搜索树为完全二叉树,其比较次数为:O(log2^n)
最差情况下: 二叉搜索树退化为单支树,其比较次数为:O(n)。
问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插入关键码,都可以是二叉搜索树的性能最佳?

4 和 java 类集的关系

TreeMap 和 TreeSet 即 java 中利用搜索树实现的 Map 和 Set;实际上用的是红黑树,而红黑树是一棵近似平衡的二叉搜索树,即在二叉搜索树的基础之上 + 颜色以及红黑树性质验证,关于红黑树的内容在后边笔记中再进行描述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1324226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MyBatis的ORM映射

目录 什么是ORM 一&#xff0c;列的别名 二&#xff0c;结果映射 三&#xff0c;总结 什么是ORM ORM&#xff1a;对象关系映射&#xff08;Object Relational Mapping&#xff0c;简称ORM&#xff09;模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简…

【六大排序详解】开篇 :插入排序 与 希尔排序

插入排序 与 希尔排序 六大排序之二 插入排序 与 希尔排序1 排序1.1排序的概念 2 插入排序2.1 插入排序原理2.2 排序步骤2.3 代码实现 3 希尔排序3.1 希尔排序原理3.2 排序步骤3.3 代码实现 4 时间复杂度分析 Thanks♪(&#xff65;ω&#xff65;)&#xff89;下一篇文章见&am…

统计分析绘图软件 GraphPad Prism 10 mac功能介绍

GraphPad Prism mac是一款专业的统计和绘图软件&#xff0c;主要用于生物医学研究、实验设计和数据分析。 GraphPad Prism mac功能和特点 数据导入和整理&#xff1a;GraphPad Prism 可以导入各种数据格式&#xff0c;并提供直观的界面用于整理、编辑和管理数据。用户可以轻松地…

MySQL——表的增删查改

目录 一.Create&#xff08;创建&#xff09; 1.单行数据 全列插入 2.多行数据 指定列插入 3.插入否则更新 4. 替换 二.Retrieve&#xff08;读取&#xff09; 1. select 列 查询 2.where 条件 3.结果排序 4.筛选分页结果 三.Update &#xff08;修改&#xff09;…

ROS学习笔记(七)---参数服务器

ROS学习笔记文章目录 01. ROS学习笔记(一)—Linux安装VScode 02. ROS学习笔记(二)—使用 VScode 开发 ROS 的Python程序&#xff08;简例&#xff09; 03. ROS学习笔记(三)—好用的终端Terminator 04. ROS学习笔记(四)—使用 VScode 启动launch文件运行多个节点 05. ROS学习笔…

SMARTFORMS打印问题

一、问题概述 项目中碰到EPSON针式打印机&#xff0c;SAP打印出来的三单合一&#xff0c;是想横向打印&#xff0c;结果不管怎么设置打印出来都是纵向的&#xff1b; 二、调整 1、首先调整SMARTFORMS的打印方向&#xff0c;使用T-CODE:SMARTFORMS&#xff0c;如下图&#xf…

嵌入式串口输入详细实例

学习目标 掌握串口初始化流程掌握串口输出单个字符掌握串口输出字符串掌握通过串口printf熟练掌握串口开发流程学习内容 需求 串口循环输出内容到PC机。 串口数据发送 添加Usart功能。 首先,选中Firmware,鼠标右键,点击Manage Project Items 接着,将gd32f4xx_usart.c添…

Dokit 开源库:简化 Android 应用开发的利器

Dokit 开源库&#xff1a;简化 Android 应用开发的利器 一、Dokit 简介二、Dokit 功能三、Dokit 使用3.1 DoKit Android 最新版本3.2 DoKit Android 接入步骤 四、总结 在 Android 应用开发过程中&#xff0c;我们经常需要处理调试、性能优化和用户体验等方面的问题。然而&…

【python】进阶--->并发编程之协程

一、协程 是另外一种实现多任务的方式,只不过比线程占用更小的执行单元(需要的资源).因为它自带cpu上下文,就可以在合适的时机,从一个协程切换到另一个协程. (任务数量多于cpu时)系统在很短的时间内,将cpu轮流分配给不同的任务执行,造成了多任务同时运行的错觉.而每个任务在运行…

全面解析找不到xinput1_3.dll无法继续执行代码的多种解决方案(实用教程)

xinput1_3.dll文件是什么&#xff1f; xinput1_3.dll是一个动态链接库文件&#xff0c;它是DirectInput的组件之一。DirectInput是微软公司开发的一种输入设备驱动程序&#xff0c;用于处理游戏控制器、键盘、鼠标等输入设备的信号。xinput1_3.dll文件主要负责处理游戏控制器的…

年终汇报这么写,升值加薪必有你!

#01 你这么能干&#xff0c; 老板知道吗&#xff1f; — 打工人最怕什么&#xff1f; 最怕你忙前忙后&#xff0c;干活一大堆&#xff0c;气出一身结节&#xff0c;锅还没少背&#xff0c;最后升职加薪没有你&#xff0c;出国旅游不带你&#xff1b;更怕你日常996&#xf…

C语言归并排序(合并排序)算法以及代码

合并排序是采用分治法&#xff0c;先将无序序列划分为有序子序列&#xff0c;再将有序子序列合并成一个有序序列的有效的排序算法。 原理&#xff1a;先将无序序列利用二分法划分为子序列&#xff0c;直至每个子序列只有一个元素(单元素序列必有序)&#xff0c;然后再对有序子序…

HTML5+CSS3小实例:纯CSS实现锚点平滑过渡

实例:纯CSS实现锚点平滑过渡 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"&…

宠物干货类软文怎么写?媒介盒子分享

虽然近年来生育率有所减少&#xff0c;但是养宠物的人却大大增加&#xff0c;随之而来的宠物经济也是一个值得关注的点。做宠物生意想要脱颖而出&#xff0c;可以依靠软文营销&#xff0c;其中宠物干货类软文由于其价值性能够带来较高的转化率今天媒介盒子主要来和大家聊聊宠物…

QT 前端技术 QSS(1)

伪装态是指当鼠标悬停在按钮上的时候&#xff0c;按钮的字体背景颜色等会发生改变。 这句话意思在this里面找到QTextEdit控件#后面表示指定的控件名称就是从所有QTextEdit中选出叫做lbsize的QTextEdit并对其进行后面的操作。 如果将QTextEdit#lbsize删除的话就是将this中全部的…

c语言编写http服务器(Linux下运行)

参考文章&#xff1a;https://blog.csdn.net/baixingyubxy/article/details/125964986?spm1001.2014.3001.5506 上面是详细讲解&#xff0c;我这篇是总结了他的代码&#xff0c;因为他没给整体代码 所有代码&#xff1a; #include <stdio.h> #include <stdlib.h&g…

echarts地图map点击某一区域设置选中颜色/select选中文字颜色设置无效

选中区域为红色&#xff0c;字体为白色 1.selectedMode: ‘single’,设置单选&#xff0c;多选&#xff0c;不选中 2.series/map/select属性 series: [{type: map,map: area,//单选selectedMode: single,aspectScale: 0.73,layoutCenter: [50%, 51%], //地图位置layoutSize: …

CEC2013(python):五种算法(OOA、WOA、GWO、DBO、HHO)求解CEC2013(python代码)

一、五种算法简介 1、鱼鹰优化算法OOA 2、鲸鱼优化算法WOA 3、灰狼优化算法GWO 4、蜣螂优化算法DBO 5、哈里斯鹰优化算法HHO 二、5种算法求解CEC2013 &#xff08;1&#xff09;CEC2013简介 参考文献&#xff1a; [1] Liang J J , Qu B Y , Suganthan P N , et al. Pro…

量子登月计划!Infleqtion与日本JST研发中性原子量子计算机

​&#xff08;图片来源&#xff1a;网络&#xff09; 美国量子信息公司Infleqtion&#xff0c;已被日本科学技术振兴机构&#xff08;JST&#xff09;选定为“量子登月计划”唯一的外国量子计算合作伙伴。该计划旨在增强日本的量子技术能力&#xff0c;预计将在2050年之前对日…

WinDbg调试异常(!!! second chance !!!)

以前使用windbg调试样本时不时会遇到异常并提示(!!! second chance !!!),之前也尝试查找过原因但是并没有找到,一直十分郁闷。这次又出现了异常,有时间查找原因并发现了问题所在,于是记录下分析过程。 起因 在调试一个样本,每次用windbg调试都会出现: 但是使用x64dbg调…