【数据结构与算法】手撕红黑树

数据结构(61):带你手撕红黑树的插入与删除(图文详解) 红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色。在二叉查找树的一般要求以外,对于任何有效的红黑树增加了如下的额外要求: 节点是红色或黑色。 根是黑色。 所有叶子都是黑色(叶子是NIL节点)。 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。) 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。 这些约束确保了红黑树的关键特性:从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如. 阅读详情

Python微信订餐小程序课程视频

https://edu.youkuaiyun.com/course/detail/36074

Python实战量化交易理财系统

https://edu.youkuaiyun.com/course/detail/35475

红黑树

定义

动机:

  • 二叉查找树查找、插入、删除最坏情况时间复杂度可能退化为 O(n)。

  • AVL 树很好的限制了数的高度为 O(logn),插入、删除、查找的最坏时间复杂度均为 O(logn);但删除操作最多需要做 O(logn) 次旋转。

  • 红黑树是具有如下特点的二叉查找树:

    • 每个结点是红色或黑色的
    • 根结点为黑色
    • 外结点为黑色(外界点即为 null)
    • 如果一个结点时红色,那么它的孩子必须是黑色
    • 任一结点到外结点的路径上,包含相同数目的黑结点


结点的黑高度:该结点到外结点的路径上包含的黑结点数目

红黑树的黑高度:根结点的黑高度

性质

  • 若忽略红结点而只考虑黑结点,则这棵树是平衡的
  • 任何一条路径上不能有两个连续的红结点。从任意结点触发最长的路径(红黑结点间隔组成)是最短路径(仅由黑结点组成)的 2 倍
  • 任何一个结点的左右子树的高度最多相差 2 倍
  • 红黑树的平衡性比 AVL 树更弱
  • 平均和最坏高度:O(logn)
  • 查找、插入、删除操作的平均和最坏时间复杂度是 O(logn),且仅涉及 O(1) 次旋转
  • 红黑树的高度:h = O(logn) 且 logn <= h <= 2logn

结点定义


1️⃣ key:关键字的值
2️⃣ value:关键字的存储信息
3️⃣ parent:父亲结点的引用
4️⃣ left:左子树根结点的引用
5️⃣ right:右子树根结点引用
6️⃣ color:结点颜色

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

java`class RBNodeextends Comparable, V> {
public RBNode parent;
public RBNode left;
public RBNode right;
public boolean color;
public K key;
public V value;

public RBNode(RBNode parent, K key, V value) {
this.parent = parent;
this.key = key;
this.value = value;
}
}`

插入算法

  • 查找,若查找成功则不插入并更新结点值;若查找失败,再查找失败的位置插入新结点
  • 新结点总是作为叶结点插入的
  • 新结点必须为红色
  • 若新结点的父结点是黑色,则插入过程结束
  • 若新结点的父结点是红色,则需要处理双红缺陷

这里定义 x 为新插入的结点,p 为 x 的父结点,g 为 x 的爷爷结点,u 为 x 的叔叔

双红修正

1️⃣ x 的叔叔是黑色

  • g 到 x 的路径为 LL 型
  • g 到 x 的路径为 RR 型
  • g 到 x 的路径为 LR 型
  • g 到 x 的路径为 RL 型

2️⃣ x 的叔叔是红色

实例


此时结点 50 的父亲结点 60 也为红色,需要进行双红修正。注意到,其叔叔结点 20 也是红色,只需要将父亲结点 60 和叔叔结点 20 变为黑色,再把爷爷结点 30 变为红色,结果如下图。


之后会发现,结点 30 和其父结点 70 都为红色,需要进行双红修正。而结点 30 的叔叔结点 85 为黑色,结点 30 的爷爷结点 15 到达结点 30 的路径是 RL 型,故需要先右旋,再左旋。结果如下图。

旋转操作

由于红黑树结点还拥有 parent 属性,故不能像平衡二叉树一样进行旋转(【数据结构与算法】手撕平衡二叉树),需要特殊考虑 parent的赋值。

1️⃣ RR 型

左旋


需要特别注意的是爷爷结点 g 的 parent 的设置,需要先判断 g 是左子结点还是右子结点。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

java private void leftRotate(RBNode g) { if (g != null) { RBNode p = g.right; g.right = p.left; if (p.left != null) { p.left.parent = g; } p.parent = g.parent; if (g.parent == null) { this.root = p; } else if (g.parent.left == g) { g.parent.left = p; } else { g.parent.right = p; } p.left = g; g.parent = p; }
2️⃣ LL 型

右旋


需要特别注意的是爷爷结点 g 的 parent 的设置,需要先判断 g 是左子结点还是右子结点。

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

java private void rightRotate(RBNode g) { if(g != null) { RBNode p = g.left; g.left = p.right; if(p.right != null) { p.right.parent = g; } p.parent = g.parent; if(g.parent == null) { this.root = p; } else if(g.parent.left == g) { g.parent.left = p; } else { g.parent.right = p; } p.right = g; g.parent = p; } }
3️⃣ LR 型

先对 g 的左子结点左旋,再对 g 右旋

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

java private void leftRightRotate(RBNode g) { if(g != null) { leftRotate(g.left); rightRotate(g); } }
4️⃣ RL 型

先对 g 的右子结点右旋,再对 g 左旋

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

java private void rightLeftRotate(RBNode g) { if(g != null) { rightRotate(g.right); leftRotate(g); } }

代码

1️⃣ 插入操作

代码描述

  • 如果根结点为空,则创建根结点,返回
  • 否则,根据 key 与结点关键值的比较找到插入位置
  • 创建结点并插入
  • 平衡处理
复制代码
【数据结构进阶】手撕红黑树 红黑树的介绍,以及底层代码逻辑和实现。刚刚接触编程的时候就听说有的大厂HR会让手撕红黑树。心中一直对这个数据结构保持着敬畏和向往,今天在将其撕出来后,用本篇博客加以记录,望周知。红黑树的结点包含四个成员变量,模板类型T:可以存储K或者pair类型,便于后期封装;三个指针:分别为指向左孩子结点的指针,指向右孩子结点的指针,指向父结点的指针;最后变量_col:枚举类型,可以存RED和BLACK。 阅读详情

相关推荐

手撕红黑树——C++高阶数据结构详解

带你一命通关红黑树 十五分钟手撕数据结构原理

qq_61500888的博客 1万+

Java手撕红黑树

前言 我这个人懒得不行,其实早就想学习学习红黑树了,以前只是知道这东西,也知道他是构成HashMap的底层数据结构(jdk1.8以后),但是每次一看红黑树的5条性质就头疼,不想去自习考虑这个数据结构。这个寒假终于下定决心用java手撕一遍红黑树,为了以后的面试做准备。由于这个数据结构有点庞大,我不想从基础开始讲解了,B站好多教学视频,我看了好多,但是现场手撕红黑树的,翻来翻去就那么几个。他们写代码的风格我不是太喜欢,且多是用的idea这个IDE,学生哪有钱买正版,我就直接用eclipse了,反正原理都一样,

wufeifan_learner的博客 976

Unity资源逆向解析:从APK到AssetStudio的完整实战

本文详细介绍了Unity资源逆向解析的全流程,从APK解包到使用AssetStudio深度解析Unity游戏资源。通过实战案例演示如何提取《植物大战僵尸》等游戏的素材,包括贴图、音频和3D模型,帮助开发者掌握Unity游戏逆向工程的核心技术。

weixin_30664051的博客 475

Matlab生成dsp程序——环境搭建(c2000系列[F28335、F2837x]都适用)

一、环境配置 (28377D的操作是一模一样就是硬件设置的时候需要选择28377d进行相应的设置) 1)matlab与ccs联合编译需要安装对应的matlab版本和ccs版本,且只有2016a以上的matlab支持c2000系列。具体对应关系参照: http://software-dl.ti.com/ccs/esd/documents/ccs_matlab.html 2)matlab版本确定之后,还需要安装有关于ccs的相关软件: I、TI Code Composer Studio xxxx(对应

qq_42151264的博客 2万+

使用trae自动生成前后端分离的web应用程序

使用ai自动生成前后端分离的web应用程序

一介书生 2529

深度学习---双层神经网络中矩阵的运算及其含义记录

深度学习---双层神经网络中矩阵的运算及其含义记录神经网络的正向传播与反向传播正向传播第一层的权重矩阵第一层的输入矩阵Z^1^ = W^1^X^1^ + b^1^A^1^ = σ(Z^1^)第二层的权重矩阵第二层的输入矩阵Z^2^ = W^2^A^1^ + b^2^反向传播dz^2^ = A^2^ - Ydw^2^ = 1/n dz^2^A^1T^db^2^ = 1/n np.sum(dz^2...

qq_43228441的博客 3748

保姆级教程:在RK3568上搞定PR2100K+GC2385双摄(从DTS配置到HAL层补丁)

本文详细介绍了在RK3568平台上调试PR2100K+GC2385双摄系统的完整流程,从DTS配置到HAL层补丁。涵盖硬件连接、媒体控制器拓扑验证、Camera3配置、HAL层特殊补丁及性能优化等关键步骤,帮助开发者快速解决双摄调试中的常见问题,提升嵌入式视觉系统开发效率。

weixin_28724661的博客 196

Isaac Sim 使用经验(配置要求,云服务器)

Google Colab及AutoDL都是在docker内运行,其中google colab并不支持docker指令,而依照AutoDL的相关文档,AutoDL并不直接提供docker指令。2. Google Colab/AutoDL 不支持图形化界面,图形渲染等任务,所以没有办法使用Omniverse Streaming进行直播,从而更好的对结果进行展示。对于第一点,或许存在直接手动复现镜像的可能,但是考虑到Isaac Sim/Isaac Lab由于比较新,可能不够稳定,因此还是按照官方文档进行部署。

weixin_44211433的博客 4591

本地通知与健康数据的隐私保护方案

随着移动健康(mHealth)应用的普及,本地通知与健康数据的结合为用户提供了更加个性化的健康管理体验。然而,这种便利性也带来了严峻的隐私保护挑战。本文旨在探讨如何在移动应用中实现本地通知功能的同时,确保用户健康数据的隐私安全。本地通知与健康数据结合的技术架构隐私保护的核心技术方案具体算法实现与数学模型实际应用案例分析本文首先介绍背景知识和核心概念,然后深入探讨隐私保护的技术方案,包括算法原理和数学模型。接着提供实际代码实现和应用场景分析,最后讨论未来发展趋势和挑战。

移动开发前沿的博客 1309

神经进化实践:用遗传算法替代反向传播优化神经网络

神经进化用来定义应用于深度学习的特定优化模式。在本节中,我们通过遗传算法优化简单深度学习网络的权重/参数,替换在误差反向传播训练过程中的所用优化器。

盼小辉丶的博客 3648

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: 序列化多表操作、请求与响应、视图组件(子类与拓展类)、继承GenericAPIView类重写接口
下一篇: 【谣言】指针比数组速度快?指针比数组速度慢?
pythonxxoo
博客等级 码龄5年 337粉丝 670原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值