没有对象来和我手撕红黑树吧

news2024/10/30 17:30:17

1. 红黑树的介绍

红黑树也是一种自平衡的二叉搜索树,在每一个节点增加了一个存储位来表示节点的颜色,可以是红色也可以是黑色,通过约束颜色来维持树的平衡,具有以下的性质:

  1. 每个节点不是红色就是黑色
  2. 根节点为黑色
  3. 如果一个节点为红色,那么它的两个孩子节点为黑色(一条路径上不能有两个连续的红色节点)
  4. 对于每个节点,从该节点及其所有后代所在的叶子节点的简单路径上,均包含相同数目的黑色节点
  5. 每一个叶子节点都是黑色的

2. 节点的定义

这里节点除了包含节点的值,左子树,右子树和父亲节点的引用外,还需要添加颜色的属性

static class RBTreeNode {
    public RBTreeNode left;
    public RBTreeNode right;
    public RBTreeNode parent;
    public int val;
    public COLOR color;

    public RBTreeNode(int val) {
        this.val = val;
        //新创建的节点默认是红色的
        this.color = COLOR.RED;
    }
}

颜色只有红色和黑色,可以使用枚举类来定义节点的颜色

public enum COLOR {
    RED,BLACK
}

节点默认创建为红色的原因:如果节点是黑色,那么插入时就会增加该路径黑色节点的个数,其他路径都需要增加黑色节点,节点是红色的话就不会影响黑色节点的个数,如果上一个节点也是红色,只需要向上调整节点的颜色即可

3. 插入

在寻找插入到哪个位置时,也是和二叉搜索树一样的,(需要注意的是,第一次插入之后需要手动的把 root 节点的颜色修改为黑色)当找到插入的位置之后,可以分为一下几种情况

3.1. p 是左子树

  1. cur 为红色, p 为红色,g 为黑色,u 存在且为红色

两个红色不能连在一起,此时就必须把 p 修改为黑色,然后为了保持黑色是相同的, u 也需要修改为黑色

这个时候就会有一个问题,如果 g 是一个黑色节点的子树,那么这时修改 p , u 就会增加黑色节点的数目,就需要把 g 改为红色,假如 g 就是根节点的话,还是需要把 g 改回黑色,所以说最后处理完之后,无论 g 当前是红色还是黑色,都手动的改为黑色

那如果 g 的父亲节点本身就是红色的话,证明它一定是有父亲节点的,然后按照上面的方式调整之后继续向上调整即可

  1. cur 为红色且是左节点,p 为红色,g 为黑色,u 不存在或者是黑色

如果 u 不存在,那么 cur 一定是新插入的节点,原来的肯定是不能有两个连续的红色节点的

当 u 存在且为黑色的时候

这种情况在调整的过程中会出现

对于这种情况的解决方案就是,先右旋 p ,再调整颜色

  1. cur 为红且是右节点,p 为红,g 为黑,u 不存在或 u 为黑

这种情况也应该是调整过程中出现的

此时对 p 进行一个左旋,然后交换 cur 和 p 的引用,就变成了第二种情况,继续按照第二种的情况调整就好

3.2. p 是右子树

然后就是 p 是右子树的情况,也是和上面一样的三种情况:

  1. cur 为红色, p 为红色,g 为黑色,u 存在且为红色

这种情况和上面的是一样的

  1. cur 为红色且是右节点,p 为红色,g 为黑色,u 不存在或者是黑色

只不过这次是需要右旋的,其余步骤还是和之前一样

  1. cur 为红且是左节点,p 为红,g 为黑,u 不存在或 u 为黑

当以上所有的情况都考虑完之后,还需要手动的把 root 节点的颜色改为黑色

4. 红黑树的验证

验证的话主要就是验证有没有两个红色节点相连和每条路径的黑色节点数量是否相等

先来看红色节点是否相连:只需要在遍历的过程中遇到红色节点之后,去看它的父亲节点是否是红色的即可,然后递归执行

    private boolean checkRedColor(RBTreeNode root){
        if(root == null) return true;
        if(root.color == COLOR.RED){
            RBTreeNode parent = root.parent;
            if(parent.color == COLOR.RED){
                System.out.println("两个红色节点连续了");
                return false;
            }
        }
        return checkRedColor(root.left) && checkRedColor(root.right);
    }

判断每条路径黑色节点的数量是否相同:首先求出一条路径的黑色节点的数量,然后再遍历每条路径,同时统计路径上的黑色节点的个数,和开始计算的出的黑色节点个数对比,如果不相同那么就不满足红黑树的性质

private boolean checkBlackNum(RBTreeNode root,int pathBlackNum,int blackNum){
    if(root == null) return true;
    if(root.color == COLOR.BLACK){
        pathBlackNum++;
    }
    if(root.left == null && root.right == null){
        if(pathBlackNum != blackNum){
            System.out.println("黑色节点不符合要求");
            return false;
        }
    }
    return checkBlackNum(root.left,pathBlackNum,blackNum)&&
    checkBlackNum(root.right,pathBlackNum,blackNum);
}

最后把这两种情况都结合起来,同时还需要判断根节点的颜色是否是黑色

public boolean isRBTree(){
    if(root == null) return true;
    //根节点必须为黑色
    if(root.color != COLOR.BLACK) return false;
    //存储当前红黑树中的黑色节点个数
    int blackNum = 0;
    RBTreeNode cur = root;
    while(cur!=null){
        if(cur.color == COLOR.BLACK){
            blackNum++;
        }
        cur = cur.left;
    }
    //检查是否存在两个连续的红色节点和每条路径的黑色节点是否相同
    return checkRedColor(root) && checkBlackNum(root, 0, blackNum);
}

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

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

相关文章

【网络面试篇】TCP与UDP类

目录 一、综述 1. TCP与UDP的概念 2. 特点 3. 区别 4. 对应的使用场景 二、补充 1. 基础概念 (1)面向连接 (2)可靠的 (3)字节流 2. 相关问题 (1)TCP 和 UDP 可以同时绑定…

linux:回车换行+进度条+git理解与使用以及如何解决免密码push问题

目录 特殊符号 Linux小程序---进度条 1.\n和\r的理解 2.缓冲区 3.设计简单的倒计时 4.设计简单的进度条 git-版本控制器 1.理解什么是版本控制器? 2.git的使用 3.git的其他说明 总结上传过程 特殊符号 1.(取消显化) 的作用:执行指令,但指令本身不会显化; 举个例子:我…

智能家居10G雷达感应开关模块,飞睿智能uA级别低功耗、超高灵敏度,瞬间响应快

在当今科技飞速发展的时代,智能家居已经逐渐成为人们生活中不可或缺的一部分。从智能灯光控制到智能家电的联动,每一个细节都在为我们的生活带来便利和舒适。而在众多智能家居产品中,10G 雷达感应开关模块以其独特的优势,正逐渐成…

什么品牌的护眼台灯比较好?五款目前比较好用的护眼台灯

在当今社会,近视已成为一种普遍现象,其背后的原因复杂多样。除了部分由遗传因素导致外,不良的用眼习惯和不适宜的照明环境也是不可忽视的重要因素。长时间盯着电子屏幕、阅读时光线过强或过弱、坐姿不正等,都可能给眼睛带来额外的…

redis详细教程(4.GEO,bitfield,Stream)

GEO Redis GEO 是 Redis 数据库中的一个功能模块,自 Redis 3.2 版本开始引入,专门用于处理地理位置信息。这个模块使得 Redis 能够存储并查询地理坐标,非常适合用于需要地理位置数据的应用,如实时位置查询、地理围栏、距离计算等…

Kafka 基础入门

文章内容是学习过程中的知识总结,如有纰漏,欢迎指正 文章目录 前言 1. 核心概念 1.1 Producer 1.2 broker 1.3 consumer 1.4 zookeeper 1.5 controller 1.6 Cluster 2. 逻辑组件 2.1 Topic 2.2 Partition 2.3 Replication 2.4 leader & follower 3. …

苹果生态的机器学习和同态加密

1. 引言 Apple认为隐私是一项基本人权。其保护用户隐私的工作遵循一系列隐私原则,其中一项原则是优先使用设备上的处理。通过在用户设备上本地执行计算,有助于最大限度地减少与 Apple 或其他实体共享的数据量。当然,用户可以请求由机器学习 …

甲骨文云免费20G对象存储挂载到VPS

准备条件 1.一个获取到免费vps的甲骨文账号Cloud Infrastructure | Oracle 2.一台需要挂载的VPS跳转中 - 有云短链接 3.用到的开源项目https://github.com/s3fs-fuse/s3fs-fuse 一、甲骨文账号端操作 1.1获取存储桶名称和名称空间 进入甲骨文账号,依次如图打开-存储-存储桶…

开源的GPT-4o模型使用指南,Mini-Omni2集视觉、语音和双工能力于一体的

1. Mini-Omni2 是什么? Mini-Omni2 是一个开源的多模态语言模型,旨在模拟 GPT-4o 的视觉、语音和文本处理能力。它能够理解和生成视觉、听觉和文本内容,并支持实时的语音输出和灵活的双工交互。 Mini-Omni2 由清华大学和 Inspirai 的研究人…

【C++】string 类深度解析:探秘字符串操作的核心

快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 目录 💯前言 💯为什么要学习 string 类 (一)简化操作 (二)确保安全 (三…

卷积神经网络实验三:模型优化(1)

作者有话说: 这篇文章写的还是比混乱的。因为本人也是第一次做这样的尝试,虽然接触深度学习有一年了,但是对于模型的优化仅仅是局限于理论上。通过这一次的实验,我对于模型的理解也更深了几分。我不期望这篇文章能帮你能解决多大问…

clickhouse运维篇(三):生产环境一键生成配置并快速部署ck集群

前提条件:先了解集群搭建流程是什么样,需要改哪些配置,有哪些环境,这个文章目的是简化部署。 clickhouse运维篇(一):docker-compose 快速部署clickhouse集群 clickhouse运维篇(二&am…

嵌入式浏览器 -- Chromium VS Firefox

嵌入式浏览器概念 嵌入式浏览器是嵌入式系统中的核心组件之一,用于为设备提供网络访问能力和内容显示功能。与传统PC浏览器相比,嵌入式浏览器更加注重性能优化和资源效率,同时确保核心功能可用,如HTML渲染、JavaScript支持和多媒…

CSP-J2024入门级T3:小木棍

题目链接 CSP-J2024T3:小木棍 题目描述 小 S 喜欢收集小木棍。在收集了 n n n 根长度相等的小木棍之后,他闲来无事,便用它们拼起了数字。用小木棍拼每种数字的方法如下图所示。 现在小 S 希望拼出一个正整数,满足如下条件: 拼出这个数恰好使用

Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程

Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程 Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程前言 OpenCV概述核心功能优势特点应用领域安装与使用 OpenCV_contrib概述核心功能具体模块 安装与使用一、准备工作二、下载OpenCV和OpenCV_contrib三、编译和安装OpenCV四、…

shodan5,参数使用,批量查找Mongodb未授权登录,jenkins批量挖掘

查找美国安全局漏洞 nww.nsa.gov(美国安全局官方网站) net参数使用 搜索指定的ip网段 shodan search --limit 10 --fields ip_str,port net:208.88.84.0/24 (老美国家安全局的一个网段)可能直接访问不太行,可以使用host参数,得到域名再去…

nrm的使用

在安装nrm之前,要先完成node.js的安装。 1、nrm的介绍 ‌nrm(npm registry manager)是一个npm源管理器,允许用户在不同npm源之间快速切换。 关于npm和nvm的介绍,详见文章nvm的使用-CSDN博客。 解释:比如…

图片懒加载(自定义指令)

----------------------------------------------------------- 图片懒加载自定义指令使用mock模拟随机图片列表组件如下(主要内容):配置自定义指令 图片懒加载 实现思路 使用自定义指令实现通用图片懒加载(在图片到达视口内时再…

socket编程---UDP

目录 一、socket 二、socket接口 1.流程原理 2.代码 前言 提示:这里可以添加本文要记录的大概内容: socket编程又称套接字编程,指进行网络通信程序的编写 提示:以下是本篇文章正文内容,下面案例可供参考 一、soc…

R语言机器学习算法实战系列(十四): CatBoost分类算法+SHAP值 (categorical data gradient boosting)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍CatBoost的原理CatBoost的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割设置数据对象调节参数训练模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC Curv…