news 2026/7/16 3:36:01

红黑树-插入节点的失衡调节

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
红黑树-插入节点的失衡调节

红黑树的本质依然是二叉搜索树,认为不存在相同的节点。

最近在学map、set,二者的底层数据结构都是红黑树。所以复习一下红黑树。

对于一颗红黑树,插入节点的大致流程是:插入新节点-判断当前状态是否失衡-失衡调节-插入完成。

一颗红黑树,需要满足以下基本条件

  1. 只有红黑节点(顾名思义)
  2. 根节点是黑节点
  3. 黑同路:树上每个节点,到它的任意叶子节点,黑色节点的数量相同
  4. 红孤单:红节点不允许连续
  5. 路径长度:从根节点到某个叶子节点的所有路径里,不存在一条路径,长度大于另一条路径的2倍

关于黑同路,其实就是在红黑树上任选2个点,分别作为起点和终点,那么两点之间的任何路径,经过的黑色节点都是一样的。

补充的:黑色节点是可以连续的;且一个节点的孩子可以一个是红、一个是黑。

只是插入新节点之前,还有两个问题需要澄清一下:

  1. 新节点插入到哪个地方?
  2. 插入的新节点,选择什么颜色?

新节点插入在什么地方?
只要哪个节点的子节点没满,那都可以插入。

插入的新节点,选什么颜色?
那就分类讨论一下:

  • 插入的新节点是黑色
    根据红黑树的黑同路性质,一颗正常、未失衡的红黑树,必定满足黑同路,也即——每个节点到任一叶子节点的路径,黑节点相同。
    那么,如果插入一个新的黑节点,那必定会导致所有经过它的路径,都多了1个黑节点,破坏了性质,就需要失衡调节。
  • 插入的新节点是红色
    如果新节点的父亲是黑色,那么插入之后,依然不会破坏红黑树的性质。

总而言之一句话:如果插入的是黑节点,那么必定需要失衡调节;如果插入的是红节点,至少有时候可以不用调节。

对于插入节点,我们给与它相关的节点都取个名字,方便后续表示。
[这里要插一张图]

  • cur:current,表示插入的新节点
  • par:parent,cur节点的父节点
  • unc:uncle,cur节点的叔叔,或者说是par节点的兄弟
  • gra:grand,cur节点的爷爷,也是par和unc的父节点

根据插入节点的位置和颜色情况,一共有3种分类方向,每种分类有2个可能,组合起来就是2×2×2=82 \times 2 \times 2 = 82×2×2=8种情况。

3种分类方向是:

  1. par节点在gra节点的左边还是右边,左边是L(left),右边是R(right)
  2. cur节点在par节点的左边还是右边,左边是L,右边是R
  3. cur节点的unc节点是红色还是黑色,黑色是B(black),红色是R(Red)

注:空节点视作黑节点,所以如果爷爷节点只有1个孩子,那么cur节点的叔叔视作黑色

接下来开始分类讨论如何失衡调节。

大类1:叔叔是红色(XXR)

叔叔是红色,那么一共就有如下情况:LLR、LRR、RLR、RRR

LLR

来确认一下图中情况是否是LLR:

  • L:父亲在爷爷的左边
  • L:自己在父亲的左边
  • R:叔叔的颜色是红色

调节方式是:

  • 父亲、叔叔染黑
  • 爷爷染红

调节之后如图,可判断是否满足红黑树的基本性质。

看上去挺简单的,那么把情况扩展成一般情况:

用相同方式调节之后,可以发现爷爷gra和自己的父节点都是红色,破坏了红黑树“红节点不能连续”的性质。

对于这种情况,就需要把爷爷视作cur,相应的,也就有了新的par、unc、gra。
此时,再次按照父亲、叔叔染黑;爷爷染红的方式调节。
如此不断往上调整。

那什么时候调整结束呢?

  • cur是根节点时,红黑树平衡,结束调整。
  • 或者当cur的父节点是黑色,也结束调整。

最后,还得注意把根节点给涂黑。因为当cur是根节点的孙子时,调节时会把爷爷gra给染红,那不就是把根节点给染红了嘛。

LRR

  • L:父亲在爷爷的左边
  • R:自己在父亲的右边
  • R:叔叔是红色

调节:

  • 父亲、叔叔染黑;爷爷染红
  • 接着cur标签移到爷爷处,以同样的方式进行失衡调节
  • cur的父亲是黑色,或者自己本身是根节点时,结束循环,红黑树已平衡
  • 将根节点染黑

RLR

  • R:父亲在爷爷的右边
  • L:自己在父亲的左边
  • R:叔叔是红色

调节:

  • 父亲、叔叔染黑;爷爷染红
  • cur移动到爷爷处,继续失衡判断
  • cur父亲是黑色,或者自己是根节点时,结束循环
  • 将根节点染黑

RRR

  • R:父亲在爷爷的右边
  • R:自己的爷爷的右边
  • R:叔叔是红色

调节:同上

大类2:叔叔是黑色(XXB)

叔叔是黑色,当我把四种情况都画出来后,发现新插入节点的父亲是红色,且没有兄弟,空节点视为黑色。

LLB

  • L:父亲在爷爷的左边
  • L:自己在父亲的左边
  • B:叔叔是黑色

调节:父黑爷红爷旋转

  • 父亲染黑
  • 爷爷染红
  • 爷爷右旋

关于左右旋,我的理解是类似以前的手机游戏《吃糖果》。
节点右旋:说明该节点位于其子节点右上角,那么该节点就往右旋转”落下来“,变成了自己子节点的右孩子。如果碰到了子节点的右孩子,那就顶替它,把那条连线撞上去。

节点左旋:该节点位于其子节点的左上角,左旋就是它往左旋转”掉落“,变成自己子节点的左孩子。碰到子节点原本的左孩子,就顶替它。

LRB

RLB

RRB

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/16 3:35:51

UiBot数据抓取进阶:从网页到Excel的自动化数据清洗与整合

1. UiBot数据抓取基础与实战场景很多刚接触RPA的朋友可能觉得网页数据抓取是个复杂的技术活,但实际上用UiBot操作起来比想象中简单得多。我去年帮一家电商公司做竞品监控时,就用这个功能每天自动抓取3万条商品数据,效率比人工提升了20倍不止。…

作者头像 李华
网站建设 2026/7/16 3:35:41

信奥P1289磁盘碎片整理:贪心算法与序列操作详解

1. 项目概述与核心需求解析信奥P1289“磁盘碎片整理”这道题,乍一看标题,很多同学可能会联想到操作系统里那个慢悠悠的整理碎片功能,然后一头雾水:这跟算法竞赛有什么关系?实际上,这道题是一个经典的、披着…

作者头像 李华
网站建设 2026/7/16 3:35:39

Trilium自托管安装实战:MySQL+反向代理+生产级加固

1. 项目概述:为什么Trilium值得你花两小时认真装一次Trilium Notes不是又一个“看起来很美”的笔记软件,它是一套真正能替代Notion、Obsidian甚至部分Confluence工作流的自托管知识图谱系统。我从2021年用它搭建个人第二大脑开始,到现在管理着…

作者头像 李华
网站建设 2026/7/16 3:35:33

生产环境EKS集群五大支柱:网络、安全、可观测性、成本与备份

1. 为什么生产环境EKS集群不能“照着教程点点点”就完事?“生产环境AWS EKS/K8s集群搭建全流程,看完这篇直接上手”——这个标题里藏着一个巨大的认知陷阱。很多刚接触云原生的工程师,看到“全流程”“直接上手”就以为能像装个Ubuntu桌面一样…

作者头像 李华
网站建设 2026/7/16 3:35:23

C++六边形填充程序:从图形库选型到面向对象封装实践

1. 项目概述:为什么选择C与六边形?在图形编程的领域里,我们见过太多矩形、圆形和三角形的绘制案例。当拿到“C实现的六边形填充图形程序设计”这个标题时,很多人的第一反应可能是:这有什么特别的?直接用画线…

作者头像 李华
网站建设 2026/7/16 3:34:46

《财富磨坊》三周目资源修改工具:无限货币与魔法经验指南

这次我们来看一个针对《财富磨坊》游戏的增量修改工具。这个工具的核心功能是让玩家在三周目之后能够轻松应对商店物价上涨的问题,提供无限货币、无限金币、无限彩票、无限燃料等资源修改能力,同时支持增加魔法经验和隐藏货币。对于喜欢这类增量游戏的玩…

作者头像 李华