数据结构 --- 红黑树

news2024/9/21 4:27:48

红黑树也是一种自平衡的二叉搜索树,和AVL树比较,插入和删除时,旋转的次数更少。

红黑树的特性:

  1. 所有节点都有颜色:红色或者黑色
  2. 所有null均视为黑色
  3. 红色节点不能相邻
  4. 根节点是黑色
  5. 从根节点到任意一个叶子节点,路径中的黑色节点数一样(黑色完美平衡)

构造红黑树节点 ---- 初始颜色都为红色

    static class RBNode {
        int key;
        Object value;
        String color = "red";
        RBNode left;
        RBNode right;
        RBNode parent;

        public RBNode(int key, Object value) {
            this.key = key;
            this.value = value;
        }

        // 是否是左孩子
        boolean isLeftChild() {
            return parent != null && parent.left == this;
        }

        // 找到当前节点的叔叔节点
        RBNode uncle() {
            if (parent == null || parent.parent == null) {
                return null;
            }
            if (parent.isLeftChild()) {
                return parent.parent.right;
            } else {
                return parent.parent.left;
            }
        }

        // 找到当前节点的兄弟节点
        RBNode brother() {
            if (parent == null) {
                return null;
            }
            if (this.isLeftChild()) {
                return parent.right;
            } else {
                return parent.left;
            }
        }
    }

红黑树的左旋和右旋:

右旋,如图所示:

 

 代码:

参考上图进行理解,相比较AVL树,多了一个parent节点的赋值。

    public void rightRotate(RBNode pink) {
        RBNode parent = pink.parent;
        RBNode yellow = pink.left;
        RBNode green = yellow.right;
        if (green != null) {
            green.parent = pink;
        }
        yellow.right = pink;
        yellow.parent = parent;
        pink.left = green;
        pink.parent = yellow;

        if (parent == null) {
            root = yellow;
        } else if (parent.left == pink) {
            parent.left = yellow;
        } else {
            parent.right = yellow;
        }
    }

    public void leftRotate(RBNode pink) {
        RBNode parent = pink.parent;
        RBNode yellow = pink.right;
        RBNode green = yellow.left;

        if (green != null) {
            green.parent = pink;
        }
        yellow.left = pink;
        yellow.parent = parent;
        pink.right = green;
        pink.parent = yellow;

        if (parent == null) {
            root = yellow;
        } else if (parent.left == pink) {
            parent.left = yellow;
        } else {
            parent.right = yellow;
        }
    }

红黑树的插入操作

红黑树的插入操作,也是遵循平衡二叉树的插入操作的。不同的是,需要维护父亲节点的信息,以及颜色信息。

    public void put(int key, Object value) {
        RBNode node = root;
        RBNode parent = null;
        while (node != null) {
            parent = node;
            if (key < node.key) {
                node = node.left;
            } else if (key > node.key) {
                node = node.right;
            } else {
                node.value = value;
                return;
            }
        }

        RBNode insert = new RBNode(key, value);
        if (parent == null) {
            root = insert;
        } else if (key < parent.key) {
            parent.left = insert;
            insert.parent = parent;
        } else {
            parent.right = insert;
            insert.parent = parent;
        }

        // 调整颜色信息
        fixRedRed(insert);
    }

每次插入操作的时候,都需要维护颜色信息,保证符合红黑树的特性:

  1. 插入的节点是根节点 ------ 首次插入节点,直接把根节点变成黑色就可以。
  2. 插入的节点父节点是黑色 ------- 树的红黑树性质不会改变,直接插入即可
  3. 插入的节点父亲是红色节点 -------- 出现红红相邻的情况,此时就需要调整红黑树了
    1. 叔叔节点是红色 ---  平衡方法如下:
      1. 父亲节点和叔叔节点都变成黑色,祖父节点变成红色
      2. 此时需要调整祖父节点的颜色信息了,其实就是递归调用,传参树祖父节点
    2. 叔叔节点是黑色 --- 四种情况
      1. LL:父亲节点是左孩子,插入的节点也是左孩子
        1. 父节点变黑,祖父节点变红,以祖父节点为根,执行一次右旋操作
      2. LR:父亲节点是左孩子,插入的节点是右孩子
        1. 以父亲节点为根执行一次左旋操作--- 此时得到了LL结构
        2. 新的父亲节点变黑(插入的节点),祖父节点变红,以祖父节点为根,执行一次右旋操作
      3. RR:父亲节点是右孩子,插入的节点也是右孩子
        1. 父节点变黑,祖父节点变红,以祖父节点为根,执行一次左旋操作
      4. RL:父亲节点是右孩子,插入的节点是左孩子
        1. 以父亲节点为根执行一次右旋操作--- 此时得到了RR结构
        2. 新的父亲节点变黑(插入的节点),祖父节点变红,以祖父节点为根,执行一次左旋操作
    private void fixRedRed(RBNode x) {
        // 1、插入的是根节点,变黑返回
        if (x == root) {
            x.color = "black";
            return;
        }
        // 2、父节点为黑色,直接返回
        if (isBlack(x.parent)) {
            return;
        }

        // 父亲节点为红色,红红相邻
        RBNode uncle = x.uncle();
        RBNode parent = x.parent;
        RBNode grandparent = parent.parent;

        //3、叔叔节点是红色
        if (isRed(uncle)) {
            parent.color = "black";
            uncle.color = "black";
            grandparent.color = "red";
            fixRedRed(grandparent);
            return;
        }

        //4、 叔叔节点是黑色 ,
        if (parent.isLeftChild()) { // 父亲左孩子
            if (x.isLeftChild()) { // 插入节点在左边
                // LL
                parent.color = "black";
                grandparent.color = "red";
                rightRotate(grandparent);
            } else { // 插入节点在右边
                // LR
                leftRotate(parent);
                x.color = "black";
                grandparent.color = "red";
                rightRotate(grandparent);
            }
        } else { // 父亲右孩子
            if (!x.isLeftChild()) { // 插入节点在右边
                // RR
                parent.color = "black";
                grandparent.color = "red";
                leftRotate(grandparent);
            } else { // 插入节点在左边
                // RL
                rightRotate(parent);
                x.color = "black";
                grandparent.color = "red";
                leftRotate(grandparent);
            }
        }
    }

红黑树节点的删除

肝不动了,后面在补吧

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

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

相关文章

5分钟带你了解,SAS硬盘和SATA硬盘的区别?

一、SAS和SATA的关系 SAS的接口技术可以向下兼容SATA。具体来说&#xff0c;二者的兼容性主要体现在物理层和协议层的兼容。 在物理层&#xff0c;SAS接口和SATA接口完全兼容&#xff0c;SATA硬盘可以直接使用在SAS的环境中&#xff0c;从接口标准上而言&#xff0c;SATA是SAS的…

接口隔离原则:接口里的方法,你都用得到吗?

文章目录 前言接口隔离原则1、角色的合理划分2、定制服务3、接口污染 胖接口减肥总结 前言 在前面几篇文章中中&#xff0c;我们讲的设计原则基本上都是关于如何设计一个类。SRP 告诉我们&#xff0c;一个类的变化来源应该是单一的&#xff1b;OCP 说&#xff0c;不要随意修改…

Fiddler抓包工具之fiddler设置断点和简单的并发测试

断点有两种方式&#xff1a; 1、全局断点 2、局部断点 全局断点 全局断点的特点是&#xff1a;不能针对一个请求&#xff0c;是给所有抓到的请求打断点 全局断点如何设置&#xff1a; 1、快速设置断点&#xff1a;直接点击底部状态栏断点处 &#xff1b;点击第一下是请求…

比赛记录:Educational Codeforces Round 149 (Rated for Div. 2) A~D

传送门:CF 前提提要:这场狠狠的掉分.C题刚开始少了一个特判,导致自己对自己的构造方法产生了疑问,然后就一直在做无用思考,后来交的时候排名就贼后面,然后D题的题面简直稀烂(虽然D题看懂之后极其简单…),赛时根本看不懂D题意,最终rating掉完.不亏是教育场,被狠狠的教育了 A题…

Web的基本漏洞--命令执行漏洞

目录 一、命令执行漏洞 1.命令执行漏洞的原理 2.命令执行漏洞分类 3.命令执行漏洞的危害 4.命令执行漏洞的防范措施 5.命令执行漏洞的绕过 一、命令执行漏洞 命令执行漏洞是指攻击者可以随意执行系统命令。它属于高危漏洞之一&#xff0c;也属于代码执行的范畴。命令执行…

内置工具横向移动

IPCSchtasks IPC: IPC$是共享"命令管道"的资源&#xff0c;它是为了让进程通信而开放的命名管道&#xff0c;连接双方可以建立安全的通道并以此通道进行加密数据交换&#xff0c;从而实现对远程计算机的访问。 利用条件&#xff1a; 1、开放139、445 2、目标开启…

Node.js V10.24.1 安装步骤(node、cnpm、yarn、vue)

一、下载node.js 下载地址&#xff1a;Download | Node.js 要下载历史低版本请点击“Previous Releases” Previous Releases 本文章以V10.24.1为例 &#xff0c;下载64位msi 二、安装 下载完成后&#xff0c;一直点击Next直到安装完成&#xff0c;可以自己修改安装位置。…

09.二叉树

09.二叉树 1.树型结构 1.1概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。它具有以下的特点&…

收到字节offer,我却拒绝了...

前言&#xff1a; 大四快毕业了&#xff0c;在等待读研的期间无事可做&#xff0c;所以打算暑期找个实习。 忠告&#xff1a; 本人投了字节某测试岗&#xff0c;看到要求是测开的要求&#xff08;科班出身需要熟悉一种语言&#xff09;&#xff0c;就以为面完发技术岗的offe…

note注解

元注解 注解在注解上面的注解称为元注解。主要有以下五种。 Retention 表明注解存活时间 Documented 将注解元素放到Javadoc文档中 Target 注解可以使用到的地方 在ElementType[]中主要有以下几种类型 TYPE&#xff1a;类型&#xff08;比如类、注解、枚举&#xff09; FIELD&…

Refresh解析

目录 后置处理器PostProcessor PostProcessor的种类 Aware 事件监听模式 Spring容器的刷新逻辑 ApplicationContext refresh的流程概述 1---prepareRefresh 2---obtainFreshBeanFactory 3---prepareBeanFactory 4---postProcessBeanFactory 5---invokeBeanFactoryPo…

【正点原子STM32连载】 第二十一章 通用定时器实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十…

海康萤石摄像头本地局域网拉流保存

海康萤石的视频cp1型号&#xff0c;获取局域网的视频流&#xff1a;rtsp 拉流方法 首先需要在软件中打开rtsp开关&#xff0c;然后使用nmap工具测试下摄像头开放的端口号&#xff0c;一定会有一个554端口开放 $ nmap 192.168.0.105 PORT STATE SERVICE 554/tcp open r…

什么是Flink CDC,以及如何使用

什么是Flink CDC&#xff0c;以及如何使用 CDC介绍Flink CDC适用于场景&#xff1f;Flink CDC 的简单用例数据库配置创建数据库和相应的表开启mysql数据库bin-log日志1.如果是服务器2.如果在Windows使用小皮 搭建Flink CDC java环境添加maven相关pom构建Sinkmain配置运行 操作数…

盘点中国开发的有影响力的编程技术产品,道阻且长,行则将至

计算机诞生之后&#xff0c;程序员需要给计算机发送指令&#xff0c;能够准确地定义计算机所需要使用的数据&#xff0c;并精确地定义在不同情况下所应当采取的行动。计算机需要能够识别并执行指令。这个“指令”就是我们今天的“编程语言”&#xff0c;一种计算机和人都能识别…

【十】设计模式~~~结构型模式~~~享元模式(Java)

【学习难度&#xff1a;★★★★☆&#xff0c;使用频率&#xff1a;★☆☆☆☆】 5.1. 模式动机 面向对象技术可以很好地解决一些灵活性或可扩展性问题&#xff0c;但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时&#xff0c;将导致运行代价过高&#xff0…

路径规划算法:基于自私羊群优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于自私羊群优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于自私羊群优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

图解max{X,Y}和min{X,Y}并求相关概率

图解max{X,Y}和min{X,Y}并求相关概率 对max{X,Y}或min{X,Y}进行分解再求解 P ( m a x { X , Y } ≥ c ) P [ ( X ≥ c ) ∪ ( Y ≥ c ) ] P ( m a x { X , Y } ≤ c ) P [ ( X ≤ c ) ∩ ( Y ≤ c ) ] P ( m i n { X , Y } ≥ c ) P [ ( X ≥ c ) ∩ ( Y ≥ c ) ] P ( m i…

2022年12月1日郑州大学新闻与传播学院副院长博导郑*侠—社科申报注意事项

郑老师&#xff08;1项重点社科&#xff0c;2项青年社科&#xff09;&#xff0c; 一、选题 随时关注 最新国家层面信息&#xff1a;二十大报告&#xff0c;重要文件&#xff0c;重点项目信息 选题方向&#xff1a;问题导向 时代问题—学术问题—现实问题 题目命名&#xf…

基于微信小程序的社区生活管理

一&#xff1a;系统使用到的技术栈 SSMJSP原生JSMysql微信小程序 二&#xff1a;表结构 三&#xff1a;功能截图 四.源码获取