当前位置: 首页 > news >正文

二叉搜索树的基本操作 || TreeMap和TreeSet介绍

目录

前言:

二叉搜索树的插入

代码实现

二叉搜索树的查找

代码实现

二叉搜索树的删除

代码实现

TreeMap介绍

源码展现

 TreeSet介绍

源码展现

 小结:


前言:

😄现在很多地方都需要去查找某个数据,那么查找的效率就显得尤为重要了。二叉搜索树是一颗左孩子比父亲小,右孩子比父亲大的一棵树。那么在这个基础上查找某个数据,一次比较就可以排除一半数据,效率是相当高的。

二叉搜索树的插入

😯拿到一个数据,首先判断根节点是否为空,如果为空就往根节点处插入。否则依次向下比较,比它大就往右走,比它小都往左走。直到走到叶子节点,就可以插入了。这个时候需记录这个叶子节点,然后去判断往右边还是左边插入数据。

代码实现

 public boolean insert(int val) {
        if(root == null) {
            TreeNode newNode = new TreeNode(val);
            root = newNode;
            return true;
        }
        TreeNode cur = root;
        TreeNode prev = null;
        while(cur != null) {
            if(val > cur.val) {
                prev = cur;
                cur = cur.right;
            }else if(val < cur.val) {
                prev = cur;
                cur = cur.left;
            }else {
                return false;
            }
        }
        //最终可能在左面和右面插入
        TreeNode newNode = new TreeNode(val);
        if(val < prev.val) {
            prev.left = newNode;
        }else {
            prev.right = newNode;
        }
        return true;
    }

二叉搜索树的查找

😃定义cur去遍历二叉树。首先判断cur处位置的val值是否和需查找值一致,如果一致则直接返回这个节点,否则就去判断cur该往左还是右走。如果cur为空,则说明二叉树遍历完成,也没有找到目标值,返回null。

代码实现

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

二叉搜索树的删除

🎈我们可以想到要删除树中的某一个节点,需连将这个节点的上一个节点和下一个节点连接起来。所以定义前后指针prev,cur去遍历树。当cur找到后去删除这个节点。

🎈删除树中的某一个节点,如果这个节点的左右都不为空,或者这个节点的左树为空,又或者这个节点的右树为空。它们的删除方法都不相同。因此我们将这些可能都枚举出来,逐个去判断。

🎈左树为空的情况,如果要删除的节点为根节点,直接调整根节点为它的右子树。如果要删除的节点在上一个节点的右边,直接连接上一个节点的right到这个节点的right。如果要删除的节点在上一个节点的左边,连接上一个节点left到这个节点的right。

🎈右树为空的情况,如果要删除的节点为根节点,直接调整根节点为它的左子树。如果要删除的节点在上一个节点的右边,直接连接上一个节点的right到这个节点的left。如果要删除的节点在上一个节点的左边,连接上一个节点left到这个节点的left。

🎈如果要删除节点的左右都不为空,不论怎样去连接都会打破树的结构,因此提出替罪羊式删除法。在这个节点左树中找到最大值,或者右树中找到最小值,就可以替换这个节点的值,保证这颗树依然维持二叉搜索树的结构特点。那么就只需要删除左树中的最大值或者右树中的最小值(替罪羊)。当在右树中找到最小的值,替换完成后。删除这个节点时,这个节点可能在上一个节点的左边,也可能在右边(右树只有一个节点)。在左边就直接连接上一个节点的left到这个节点right。在右边就直接连接上一个节点right到这个节点的right。

代码实现

public boolean remove(int val) {
        TreeNode cur = root;
        TreeNode prev = null;
        while(cur != null) {
            if(val > cur.val) {
                prev = cur;
                cur = cur.right;
            }else if(val < cur.val) {
                prev = cur;
                cur = cur.left;
            }else {
                removeNode(prev, cur);
                return true;
            }
        }
        return false;
    }
 private void removeNode(TreeNode prev, TreeNode cur) {
        //删除分为三种情况
        //左树为空  右树为空  左右树都不为空
        if(cur.left == null) {
            //可能删除根节点  可能删除prev的右节点  可能删除prev的左节点
            if(cur == root) {
                root = root.right;
            }else if(cur == prev.right) {
                prev.right = cur.right;
            }else {
                prev.left = cur.right;
            }
        }else if(cur.right == null) {
            if(cur == root) {
                root = root.left;
            }else if(cur == prev.right) {
                prev.right = cur.left;
            }else {
                prev.left = cur.left;
            }

        }else {
            //替罪羊式删除法
            //左树中找最大的/右树中找最小的
            //就可以替换要被删除的元素,接下来只需删除左面最大或者右面最小的节点
            TreeNode target = cur.right;
            TreeNode targetParent = cur;
            while(target.left != null) {
                targetParent = target;
                target = target.left;
            }
            cur.val = target.val;
            //最终要删除的节点可能在targetParent左和右
            if(target == targetParent.left) {
                targetParent.left = target.right;
            }else {
                targetParent.right = target.right;
            }
        }
    }

TreeMap介绍

🪖TreeMap的底层是一颗红黑树,红黑树是建立在二叉搜索树结构上的。由于搜索树在极端情况下它的单分支会很长,这样就会增加查找的效率。在这个基础上提出的AVL树,将它的单分支进行旋转。由于可能旋转的次数会很多,又在这个基础上提出了红黑树。

🪖TreeMap中数据存储,是按照键值对的方式去存储(key - val)。由于搜索树中不会存在相同的数据,即TreeMap中的key是唯一的。如果插入相同的key会更新其原来key的val值,那么相应的key是不可以修改的,但是val值可以修改。

🪖TreeMap是实现map接口的,相对于Iterable接口这个接口是独立的。可以调用entrySet方法将TreeMap中的(key - val)取出来为Entry类型,存储到set集合当中去组织。也可以调用keySet或者values方法可以单独将key或者val取出来,分别存储到set集合或者collection集合当中去组织。

🪖由于TreeMap底层是红黑树,那么它的key是必须具有比较性。如果提供比较器优先调用比较器,否则实现Comparable接口重写compareTo方法。key不能为null,因为null无法比较,否则会抛NullPointerException异常。

源码展现

 

 

 

 TreeSet介绍

🤞TreeSet只存储key。它底层是用TreeMap实现的,只是所有的val值都是Object对象。TreeSet是实现set接口的,它是在Iterable接口下。

🤞那么相应的TreeSet底层也是红黑树,key值也就是唯一的,不可以添加相同的key。它的key也需具有可比较性。TreeSet具有天然去重的功能。

源码展现

 

 

 

 

 小结:

🐵在学习一些集合时,我们在理解的基础上可以去看一些源码,这样也会加深对其的理解性。

相关文章:

  • 超详细的数据结构---顺序表的有关教程
  • Exchange Server 2016 安装部署
  • 【C51单片机】中断系统之单一外中断应用
  • 2.2 Linux系统的目录结构与文件类型
  • jedis:使用事务开启watch监控
  • 【趣学算法】第一章 算法之美(上)
  • 以MapBox为核心构建Vue地图组件库教程
  • Web链接测试如何做?
  • 【不是问题的问题】为什么复位中断服务程序里面直接调用的main函数,难道所有程序都在复位中断里面执行的?
  • 【ViT 微调时关于position embedding如何插值(interpolate)的详解】
  • 动态内存管理(malloc free calloc realloc)
  • C语言/C++内存管理
  • 【FPGA】什么是串行通信?
  • c语言必背100代码,C语言代码大全(c语言必背项目代码)
  • JavaEE——No.2 套接字编程(TCP)
  • Apache的80端口被占用以及访问时报错403
  • CAP理论的例子讲解
  • CODING 缺陷管理功能正式开始公测
  • ES2017异步函数现已正式可用
  • javascript 哈希表
  • js对象的深浅拷贝
  • Laravel5.4 Queues队列学习
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • Python十分钟制作属于你自己的个性logo
  • Redash本地开发环境搭建
  • Redis字符串类型内部编码剖析
  • Vim Clutch | 面向脚踏板编程……
  • 初探 Vue 生命周期和钩子函数
  • 好的网址,关于.net 4.0 ,vs 2010
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 普通函数和构造函数的区别
  • 使用docker-compose进行多节点部署
  • 消息队列系列二(IOT中消息队列的应用)
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 一、python与pycharm的安装
  • 责任链模式的两种实现
  • 正则表达式
  • zabbix3.2监控linux磁盘IO
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • (2020)Java后端开发----(面试题和笔试题)
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (BFS)hdoj2377-Bus Pass
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (HAL库版)freeRTOS移植STMF103
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • .htaccess配置常用技巧
  • .Net CF下精确的计时器
  • .net core使用ef 6
  • .sh