TreeMap的put()插入红色节点后调用fixAfterInsertion()处理红-红冲突,分三种情形:叔父为红则变色并上移;LL型右旋加变色;LR型先左旋转LL再处理,最终根节点染黑以满足红黑树五性质。

直接看 TreeMap 的 put() 方法入口,关键逻辑在插入后调用的 fixAfterInsertion() —— 这是整个自平衡调整的核心,所有旋转和变色都发生在这里。
定位核心方法:从 put 到 fixAfterInsertion
插入新节点时,put() 先按二叉搜索树规则找到叶子位置,新建红色节点挂载,然后立即调用 fixAfterInsertion(Entry。这个方法接收刚插入的节点(标记为 x),只在满足三个条件时才真正进入调整逻辑:
• x != null
• x != root
• x.parent.color == RED
不满足任一条件就跳过调整——说明当前结构仍符合红黑树五条性质。
理解调整逻辑的三类场景
fixAfterInsertion 本质是处理「红-红冲突」,即父节点为红,违反性质4(红节点子节点必须为黑)。它通过判断 x 相对于祖父节点 g 的位置关系,分三种情况处理:
-
情形1:叔父节点 y 是红色 → 简单变色:把父节点
p和叔父y染黑,祖父g染红;再将x上移到g,继续向上检查 -
情形2:x 是父节点的左孩子,父节点是祖父的左孩子(LL) → 右旋 + 变色:先对祖父
g右旋,再交换p和g颜色 -
情形3:x 是父节点的右孩子,父节点是祖父的左孩子(LR) → 先左旋父节点,再按情形2处理:即先对
p左旋使结构转为 LL,再对新祖父右旋并变色
这三类覆盖了所有可能的红-红路径,JDK 实现中用 if-else if-else 分支明确区分左右子树方向,并复用 rotateLeft() 和 rotateRight() 方法完成物理结构调整。
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
注意颜色定义与边界细节
源码中用布尔值表示颜色:static final boolean BLACK = true,RED = false。这意味着所有新节点默认构造为 color = BLACK,但 put() 中显式设为红色:e.color = RED。根节点最终强制染黑——这是在 fixAfterInsertion 结束后、或插入完成时由逻辑保证的(例如当 x 上移至根,循环退出后会单独执行 root.color = BLACK)。
验证是否平衡:对照五条红黑树性质
每次调整后,可手动核对是否仍满足全部五条性质:
• 节点非红即黑
• 根为黑
• 所有叶子(null)视为黑节点
• 红节点子节点全为黑
• 任意节点到各叶子的黑节点数相等(黑高不变)
其中第5条最难直观验证,但 JDK 的实现确保:变色不改变黑高,单/双旋也不改变各路径黑节点数量——这是红黑树能维持 O(log n) 性能的根本保障。










