红黑树(Red Black Tree)
简介(Introduction)
红黑树 ( Red Black Tree)是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
描述(Description)
- 一棵红黑树是满足下面 红黑性质 的 二叉搜索树:
- 结点是红色或黑色。
- 根结点是黑色。
- 每个叶节点 \((NIL)\) 都是黑色。(一般不在图中画出)
- 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)
- 从任一节结点其每个叶子的所有路径都包含相同数目的黑色结点。
- 性质:从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。 即:设最短路径为 \(r\),说明最短路径均由黑色节点组成,即:黑色节点的个数为 \(r\),在根节点到叶节点之间两两黑色节点中间插入一个红色节点,则最长路径长度为 \(2r - 1\)
- 旋转:
当对红黑树进行插入和删除等操作时,对树做了修改,那么可能会违背红黑树的性质。
为了保持红黑树的性质,则可以通过对树进行旋转【左旋 \((zag)\) 和右旋 $ (zig)$ 】,即修改树中某些结点的颜色及指针结构,以达到对红黑树进行插入、删除结点等操作时,红黑树依然能保持它特有的性质
- 插入:
- 若被插入的节点是根节点。
- 直接把此节点涂为黑色。
- 若被插入的节点的父节点是黑色。
- 什么也不需要做。
- 若被插入的节点的父节点是红色。
- Case1:当前节点的祖父节点的另一个子节点(叔叔节点)也是红色。
- 将“父节点”设为黑色。
- 将“叔叔节点”设为黑色。
- 将“祖父节点”设为“红色”。
- 将“祖父节点”设为“当前节点”(红色节点);即,之后继续对“当前节点”进行操作。
- Case2:叔叔节点是黑色,且当前节点是其父节点的右孩子
- 将“父节点”作为“新的当前节点”。
- 以“新的当前节点”为支点进行 左旋。
- Case3:叔叔节点是黑色,且当前节点是其父节点的左孩子
- 将“父节点”设为“黑色”。
- 将“祖父节点”设为“红色”。
- 以“祖父节点”为支点进行 右旋。
- Case1:当前节点的祖父节点的另一个子节点(叔叔节点)也是红色。
- 若被插入的节点是根节点。
Tips:红黑树的删除操作较为复杂,408 考的概率极低,删除示例考完后后续再进行补充~
- 删除:
- 若 \(x\) 指向一个"红+黑"节点。
- 将 \(x\) 设为一个"黑"节点即可。
- 若 \(x\) 指向根。
- 将 \(x\) 设为一个"黑"节点即可。
- 若 \(x\) 指向一个"黑+黑"节点。
- Case1: \(x\) 的兄弟节点是红色。
- 将 \(x\) 的兄弟节点设为“黑色”。
- 将 \(x\) 的父节点设为“红色”。
- 对 \(x\) 的父节点进行 左旋。
- 左旋后,重新设置 \(x\) 的兄弟节点。
- Case2: \(x\) 的兄弟节点是黑色, \(x\) 的兄弟节点的两个孩子都是黑色。
- 将 \(x\) 的兄弟节点设为“红色”。
- 设置“ \(x\) 的父节点”为“新的 \(x\) 节点”。
- Case3: \(x\) 的兄弟节点是黑色; \(x\) 的兄弟节点的左孩子是红色,右孩子是黑色的。
- 将 \(x\) 兄弟节点的左孩子设为“黑色”。
- 将 \(x\) 兄弟节点设为“红色”。
- 对 \(x\) 的兄弟节点进行 右旋。
- 右旋后,重新设置 \(x\) 的兄弟节点。
- Case4: \(x\) 的兄弟节点是黑色; \(x\) 的兄弟节点的右孩子是红色的, \(x\) 的兄弟节点的左孩子任意颜色。
- 将 \(x\) 父节点颜色赋值给 \(x\) 的兄弟节点。
- 将 \(x\) 父节点设为“黑色”。
- 将 \(x\) 兄弟节点的右子节设为“黑色”。
- 对 \(x\) 的父节点进行 左旋。
- Case1: \(x\) 的兄弟节点是红色。
- 若 \(x\) 指向一个"红+黑"节点。
时间复杂度:\(O(\log n)\)
示例(E \(x\) ample)
-
红黑树:
-
插入节点:
-
删除节点:
-
插入示例: