以某节点 y 为轴,将其左子 x 提上来,y 变为 x 的右子;x 的原右子树变为 y 的左子树。与左旋互为逆操作。
插入
插入分两步:
按 BST 规则插入新节点,并先标为红色(这样不破坏性质 5,只可能破坏性质 2 或 4)。
若违反「根为黑」或「无连续红」,则通过变色 + 旋转修复。
下面用「当前节点」指我们正在关注、可能违反性质的那个节点(新节点或因修复而上溯到的节点)。
插入后的情况划分
设新节点为 z,父节点为 p,叔节点为 u(父的兄弟),祖父为 g。
Case 1:z 是根 → 涂黑即可。
Case 2:p 是黑 → 不破坏性质,结束。
Case 3:p 是红,则必有 g 为黑(根为黑)。看 u:
Case 3a:u 是红 → 将 p、u 涂黑,g 涂红,然后令「当前节点」= g 继续上溯。
Case 3b:u 是黑或 NIL → 通过旋转 + 变色统一到「当前节点在根或父为黑」:
若 z、p、g 呈「左-左」或「右-右」:对 g 做一次单旋(p 在左则右旋,p 在右则左旋),并交换 p 与 g 的颜色。
若呈「左-右」或「右-左」:先对 p 做一次单旋,变成「左-左」或「右-右」,再对 g 做单旋并变色。
flowchart LR
A[新节点 z 标红] --> B{z 是根?}
B -->|是| C[z 涂黑]
B -->|否| D{父 p 是黑?}
D -->|是| E[结束]
D -->|否| F{叔 u 是红?}
F -->|是| G[p,u 涂黑 g 涂红 上溯]
G --> B
F -->|否| H[旋转+变色]
H --> E
修复时以「当前节点」为参考(即替代被删位置的那个节点),若当前节点是红则涂黑即可;若是黑则需按兄弟及其子节点颜色分多种 Case 处理(兄弟为红则先旋转使兄弟为黑,再按兄弟为黑的情况处理;兄弟为黑时再分子节点是否有红等),通过旋转和变色最终恢复黑高。具体 Case 较多,可查阅《算法导论》或标准实现。
type RBNode struct { Val int Color bool// true=红 false=黑 Left *RBNode Right *RBNode Parent *RBNode }
type RBTree struct { Root *RBNode }
funcNewRBTree() *RBTree { return &RBTree{} }
func(t *RBTree) isRed(n *RBNode) bool { return n != nil && n.Color == RED }
func(t *RBTree) isBlack(n *RBNode) bool { return n == nil || n.Color == BLACK }
// 左旋:以 x 为轴,把右子 y 提上来 func(t *RBTree) leftRotate(x *RBNode) { if x == nil || x.Right == nil { return } y := x.Right x.Right = y.Left if y.Left != nil { y.Left.Parent = x } y.Parent = x.Parent if x.Parent == nil { t.Root = y } elseif x == x.Parent.Left { x.Parent.Left = y } else { x.Parent.Right = y } y.Left = x x.Parent = y }
// 右旋:以 y 为轴,把左子 x 提上来 func(t *RBTree) rightRotate(y *RBNode) { if y == nil || y.Left == nil { return } x := y.Left y.Left = x.Right if x.Right != nil { x.Right.Parent = y } x.Parent = y.Parent if y.Parent == nil { t.Root = x } elseif y == y.Parent.Left { y.Parent.Left = x } else { y.Parent.Right = x } x.Right = y y.Parent = x }
// Insert 插入并修复红黑性质 func(t *RBTree) Insert(val int) { z := &RBNode{Val: val, Color: RED} var parent *RBNode cur := t.Root for cur != nil { parent = cur if val < cur.Val { cur = cur.Left } else { cur = cur.Right } } z.Parent = parent if parent == nil { t.Root = z } elseif val < parent.Val { parent.Left = z } else { parent.Right = z } t.insertFixup(z) }
func(t *RBTree) insertFixup(z *RBNode) { for z != nil && z != t.Root && t.isRed(z.Parent) { p := z.Parent g := p.Parent if p == g.Left { u := g.Right // 叔 if t.isRed(u) { // Case 3a:叔红 → 父、叔涂黑,祖父涂红,上溯 p.Color = BLACK u.Color = BLACK g.Color = RED z = g } else { if z == p.Right { // 左-右 → 先对父左旋变成左-左 z = p t.leftRotate(z) p = z.Parent g = p.Parent } // 左-左:祖父右旋,父与祖父换色 p.Color = BLACK g.Color = RED t.rightRotate(g) z = p } } else { u := g.Left if t.isRed(u) { p.Color = BLACK u.Color = BLACK g.Color = RED z = g } else { if z == p.Left { z = p t.rightRotate(z) p = z.Parent g = p.Parent } p.Color = BLACK g.Color = RED t.leftRotate(g) z = p } } } t.Root.Color = BLACK }
// Search 查找 func(t *RBTree) Search(val int) *RBNode { cur := t.Root for cur != nil && cur.Val != val { if val < cur.Val { cur = cur.Left } else { cur = cur.Right } } return cur }
// InOrder 中序遍历(用于验证 BST 性质) func(t *RBTree) InOrder(n *RBNode, result *[]int) { if n == nil { return } t.InOrder(n.Left, result) *result = append(*result, n.Val) t.InOrder(n.Right, result) }
funcmain() { tree := NewRBTree() for _, v := range []int{7, 3, 18, 10, 22, 8, 11, 26} { tree.Insert(v) } var order []int tree.InOrder(tree.Root, &order) fmt.Println("中序:", order) // 有序 fmt.Println("根:", tree.Root.Val) // 根为黑 fmt.Println("查10:", tree.Search(10)) // 非 nil }