手撕红黑树的构建与验证

news2025/2/3 22:42:19

上篇文章我们介绍了AVL树的构建与适用场景,我们知道了AVL树虽然查找效率很高,但是不适合频繁插入或删除的场景。为了解决这个问题又诞生了新的数据结构:红黑树

那么本篇文章就着重介绍红黑树的性质与如何构建。

1.红黑树的性质

1.结点颜色非黑即红

2.根结点一定是红色的

3.不能有两个连续的红色结点(父和子不能同时是红色)

4.对于每个结点,到叶节点的每一条简单路径的黑色结点数量相同

5.叶节点是黑色的(这里的叶节点指的的空结点)

从这五个性质可以推导出来:最长路径的长度最多是最短路径的两倍

(最长路径:黑红交替,最短路径:全黑,再结合性质4就能得到推论)

举个例子:

2.红黑树的构建

因为我们是边插入边调节树结构,所以我们只要把所有的情况列举出来转换为代码即可

值得注意的是:每次我们新插入结点都默认为红色,因为在插入之前我们的树一定是满足所有性质的,一旦插入的是黑色结点,那么一定会违反性质4,所以先插入红色在考虑调整。

结点结构:

static class rbNode{
        int val;
        RBColor rbColor = RBColor.Red;//默认为红
        rbNode parent;
        rbNode left;
        rbNode right;
    }

public enum RBColor {
    Red,
    Black
}

刚开始的插入和二叉搜索树的插入一样,只是插入完要分情况调节树

情况1

注:以下情况省略了叶子结点(null),只截取一小部分。

 

插入cur结点后不满足性质3,所以需要调节

parent和uncle都由红变黑

grandparent由红变黑,如果不变就违反了性质4,因为grandparent也可能存在父节点,这里只是我们没有画出。 如果grandparent是根结点,最后再变为黑即可。

情况1因为grandparent是红色的所以需要继续向上调整【因为还可能不满足性质3】

情况2,3就不需要继续向上调整了

核心代码如下:

parent.rbColor = RBColor.Black;
uncle.rbColor = RBColor.Black;
grandparent.rbColor =RBColor.Red;

情况2

 

情况2不会在插入的时候出现,而是在我们向上调节的时候出现 

如何处理?

这里考虑的是图二uncle存在的情况,如果uncle不存在,那么代表我们图二的cur必须是新插入的结点,也就是:

 核心代码如下

 

rotateRight(grandparent);//直接调用上一篇AVL文章的右单旋代码即可
parent.rbColor = RBColor.Black;
grandparent.rbColor = RBColor.Red;

 

情况3

情况2考虑的是,cur和parent在其父节点同一边的情况,就是cur在parent左边,parent也在grandparent的左边。如果cur在右,parent在左又该如何处理呢?

这里最终的结果上半部分就和情况2的一致了,接下来的调节和情况2也一致 

核心代码如下:

if(cur == parent.right){//情况3
       //先左旋调节为情况2--直接用AVL写过的左旋代码
       rotateLeft(parent);
       //调换parent和cur的指向
       rbNode tmp = cur;
       cur = parent;
       parent =tmp;
}

以上都是在

if(parent == grandparent.left){//parent是grandparent的左结点

这个条件下的调节方式,如果

if(parent == grandparent.right){//parent是grandparent的左结点

只要颠倒一下left和right的即可,思路都是一样的。

3.验证红黑树

验证红黑树主要从红黑树的性质来验证

 五个性质中,1 2 5都基本上不用验证,主要是验证3 4两个性质和二叉搜索树中序遍历有序。

验证中序遍历有序

遍历即可:

void inorder(rbNode root){
        if(root == null){
            return;
        }
        inorder(root.left);
        System.out.print(root.val+" ");
        inorder(root.right);
    }

验证性质3

遍历的时候如果当前结点是红色就判断当前结点的父结点是不是红色。

void inorder(rbNode root){
        if(root == null){
            return;
        }
        inorder(root.left);
        if(root.rbColor == RBColor.Red){
            if(root.parent!=null&&root.parent.rbColor == RBColor.Red){
                System.out.println("结点"+root.val+"的父节点也是红色");
            }
        }
        System.out.print(root.val+" ");
        inorder(root.right);
    }

验证性质4

先计算一条路径黑色结点个数,得到结果以这个数为准,判断其他路径是否与之相等

static int blackNum=-1;
    static int tmpNum=0;
    static void inorder(rbNode root){
        if(root == null){
            //来到了叶子结点
            if(blackNum==-1){//说明此路径是第一条路径
                blackNum = tmpNum;
            }else{//说明此路径不是第一条路径
                if(blackNum!=tmpNum){//进行验证
                    System.out.println("不满足性质4!");
                }
            }
            return;
        }
        if(root.rbColor == RBColor.Red){
            if(root.parent!=null&&root.parent.rbColor == RBColor.Red){
                System.out.println("结点"+root.val+"的父节点也是红色");
            }
        }else{
            tmpNum++;
        }
        inorder(root.left);
        System.out.print(root.val+" ");
        inorder(root.right);
        if(root.rbColor == RBColor.Black){//代表这个黑色结点不再参与计算,这条路径不走了
            tmpNum--;
        }
    }

验证结果

 没有打印其他错误,代码正确!

验证例子:

- 场景1
{16, 3, 7, 11, 9, 26, 18, 14, 15}
- 场景2
{4, 2, 6, 1, 3, 5, 15, 7, 16, 14}

红黑树和AVL树的比较

红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O( logN),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。

对于这个logN 我作以下解释:

设红黑树有X个黑色结点,总共有N个结点,结点N的范围也就是[X,2X]。

最少:如果这N=X(完全平衡树--和AVL一样),那么时间复杂度就是logX;

最多:如果这N=2X(红黑结点交替),那么时间复杂度就是log2X;

实际上logX和log2X相差并不大,所以就认为两种树的时间复杂度一样。

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

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

相关文章

邓俊辉 《数据结构》笔记1 绪论

邓俊辉 《数据结构》笔记1 绪论 CSDN转图床总是崩,如果全写完再上传一次要调好多,感觉很麻烦,所以写一点更新一点,会持续更新 提前发出来还有个好处就是push自己更新不会咕咕咕,哈哈 参考资料 MOOC 数据结构上MOOC 数…

【计算机考研408】磁盘的初始化过程

该图是磁盘物理图 关于磁盘存储器,[柱面号盘面号扇区号]⇔外存块号 注:柱面是相对位置相同的磁道所构成的面 磁盘初始化 低级初始化(也称物理格式化) (1)分扇区 (2)用特殊数据结构…

linux后台自定义后台服务service(以filebeat举例)

文章目录一、配置攥写1)安装filebeat和配置相关修改2)常用命令二、启动顺序1)命令循序2)systemctl添加自定义系统服务(服务填写指南)3)linux的systemctl命令详解及使用教程三、遇到的坑点和报错…

谁再要你自学网络安全,请给他一大B兜

前言 作为一名6年网安工程师老菜鸟来说,我实在想不通,开发岗位那么多,为什么要来学网安? 在这里必须给那些准备入坑的同学泼几盆冷水!零基础自学网络安全?劝你还是别做梦了! 基础确实很简单&#xff0c…

2023火爆共享购商业模式概念、框架、基础制度

各位企业家及创业者朋友们,你们好。我是微三云(陈志坤),在你打开这个文章的时候,先不要急,因为任何一个能够长久、安稳、盈利的平台,背后肯定有一位看准宏观方向且耐心的人。这是一个极具颠覆性…

算法图论篇

文章目录一、DFS1.排列数字(全排列)2.n皇后3.树的重心二、BFS1.走迷宫2.八数码3.图中点的层次三、拓扑排序1.有向图的拓扑序列四、最短路1.Dijkstra2. bellman-ford3.spfa4.floyd五、求最小生成树1.Prim算法2.Kruskal算法六、二分图1.染色法判定二分图2.…

UWB汽车钥匙介绍

汽车钥匙经历了机械钥匙、遥控钥匙、PEPS、数字钥匙四个阶段,而数字钥匙又分为BLE/NFC/UWB三种技术路线。 由于UWB安全性、定位精度、作用范围明显好于BLE和NFC,因此成为汽车数字钥匙的最优技术。 PEPS与数字钥匙: PEPS是指无钥匙进入/无钥匙启动系统&a…

【爬虫】JS调试解决反爬问题系列2

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…

ubuntu arm架构各版本源整理

目录 一、x86机构 1、ubuntu 20.04 2、ubuntu 18.04 3、ubuntu 21.10 4、ubuntu 22.04 二、arm机构 1、ubuntu 20.04 2、ubuntu 18.04 3、ubuntu 21.10 4、ubuntu 22.04 三、出现的问题 1、换成国内源后报https证书问题 2、如果选择国内开源站 ​3、提示the publi…

C语言重点解剖操作符要点速记

1.在多层嵌套的时候,每一次}结束加一个注释,标记清楚结束的是哪一个。 2.大部分注释都换成了空格。 in/* */t a; 等价于 in t a;替换成一个空格。 3.# define(中间可以有空格),但是不建议。 4.全局变量,常量定义等建议加上注释…

基于昇思MindSpore Quantum,实现量子虚时演化算法

01、关于昇思MindSpore项目介绍 1.项目名称 基于昇思MindSpore Quantum,实现量子虚时演化算法 2.项目链接 https://summer-ospp.ac.cn/#/org/prodetail/221cb0176 3.项目描述 在本次项目中,我们将运用MindSpore Quantum框架在量子线路上完成虚时演…

【Django】第一课 银行账户管理系统开发

概念 django服务器开发框架是一款基于Python编程语言用于web服务器开发的框架,采用的是MTV架构模式进行分层架构。 项目的搭建 1.打开pycharm开发软件,打开开发软件的内置dos窗口操作命令行 在这里指定项目存放的磁盘路径,并使用创建djang…

算法刷题日志——dp

文章目录[打家劫舍 III](https://leetcode.cn/problems/house-robber-iii/description/)卖股票的最佳时机[买卖股票的最佳时机 II](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/)[买卖股票的最佳时机 III](https://leetcode.cn/problems/best-time-to-bu…

RK3588平台开发系列讲解(系统篇)A/B System的介绍

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、简介二、配置2.1、uboot配置2.2、system bootctrl参考沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍RK3588平台的A/B System。 一、简介 A/B System指的是存在两套可以正常工作的系统,分别存…

项目实战!!! 在docker上部署Jenkins

需求:通过docker安装jenkins,并且通过Jenkins部署项目,最终效果是只要在jenkins对某个项目点击构建,jenkins就会去gitLab上拉取最新项目的最新代码,然后根据你自己项目的pom.xml文件,把项目打包成jar&#…

选择机器视觉传感器时要注意什么

在上篇文章中小编讲解了机器视觉传感器在测量中有哪些优势,看些看过文章的朋友有了个大概的了解,但是当我们在要使用机器视觉传感器时,一定要会正确的选择,这样才能保证产品在实际运用当中可以准确的检测出产品是否存在问题&#…

什么是框架?Java开发中常用的框架有哪些?

什么是框架 “框架(Framework)"一词最早出现在建筑领域,指的是在建造房屋前期构建的建筑骨架。在编程领域,框架就是应用程序的骨架,开发人员可以在这个骨架上加入自己的东西,搭建出符合自己需求的应用…

51单片机双轴太阳能追光追日系统ULN2003步进电机

实践制作DIY- GC0097-双轴太阳能追光追日系统 一、功能说明: 基于51单片机设计-双轴太阳能追光追日系统 功能介绍: STC15W48S4系列最小系统板2个ULN2003步进电机LCD1602显示器18650锂电池锂电池充电板4个光敏电阻太阳能充电 1.双轴XY追日&#xff0c…

这波无感升级有点秀——天翼云QEMU组件热升级方案来了

虚拟化技术作为云计算时代的核心技术,近年来应用越来越广泛。目前,大多数云厂商提供的云主机都是基于KVM/QEMU虚拟化技术实现的。而随着虚拟化技术的发展,QEMU组件也在不断引入新功能并进行功能优化和问题修复。 在公有云场景中,…

【解决方案】艾美捷脂肪生成测定试剂盒的功能和应用

肥胖在世界范围内日益受到关注,在美国已达到流行程度。1它是困扰我们社会的许多主要慢性疾病的危险因素,包括心血管疾病、糖尿病和癌症。近年来,许多研究集中于确定肥胖的发病机制,这是一个增加脂肪细胞数量(脂肪细胞增…