github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/tree/rbtree_utils.go (about) 1 package tree 2 3 import ( 4 "errors" 5 6 "github.com/benz9527/xboot/lib/infra" 7 ) 8 9 func isBlack[K infra.OrderedKey, V any](node RBNode[K, V]) bool { 10 return isNilLeaf[K, V](node) || node.Color() == Black 11 } 12 13 func isRed[K infra.OrderedKey, V any](node RBNode[K, V]) bool { 14 return !isNilLeaf[K, V](node) && node.Color() == Red 15 } 16 17 func isNilLeaf[K infra.OrderedKey, V any](node RBNode[K, V]) bool { 18 return node == nil || (!node.HasKeyVal() && node.Parent() == nil && node.Left() == nil && node.Right() == nil) 19 } 20 21 func isRoot[K infra.OrderedKey, V any](node RBNode[K, V]) bool { 22 return node != nil && node.Parent() == nil 23 } 24 25 func blackDepthTo[K infra.OrderedKey, V any](target, to RBNode[K, V]) int { 26 depth := 0 27 for aux := target; aux != to; aux = aux.Parent() { 28 if isBlack[K, V](aux) { 29 depth++ 30 } 31 } 32 return depth 33 } 34 35 // rbtree rule validation utilities. 36 37 // References: 38 // https://github1s.com/minghu6/rust-minghu6/blob/master/coll_st/src/bst/rb.rs 39 40 // Inorder traversal to validate the rbtree properties. 41 func RedViolationValidate[K infra.OrderedKey, V any](tree RBTree[K, V]) error { 42 size := tree.Len() 43 var aux RBNode[K, V] = tree.Root() 44 if size < 0 || aux == nil { 45 return nil 46 } 47 48 stack := make([]RBNode[K, V], 0, size>>1) 49 defer func() { 50 clear(stack) 51 }() 52 53 for ; !isNilLeaf[K, V](aux); aux = aux.Left() { 54 stack = append(stack, aux) 55 } 56 57 for size = int64(len(stack)); size > 0; size = int64(len(stack)) { 58 if aux = stack[size-1]; isRed[K, V](aux) { 59 if (!isRoot[K, V](aux.Parent()) && isRed[K, V](aux.Parent())) || 60 (isRed[K, V](aux.Left()) || isRed[K, V](aux.Right())) { 61 return errors.New("rbtree red violation") 62 } 63 } 64 65 stack = stack[:size-1] 66 if aux.Right() != nil { 67 for aux = aux.Right(); aux != nil; aux = aux.Left() { 68 stack = append(stack, aux) 69 } 70 } 71 } 72 return nil 73 } 74 75 // BFS traversal to load all leaves. 76 func bfsLeaves[K infra.OrderedKey, V any](tree RBTree[K, V]) []RBNode[K, V] { 77 size := tree.Len() 78 var aux RBNode[K, V] = tree.Root() 79 if size < 0 || isNilLeaf[K, V](aux) { 80 return nil 81 } 82 83 leaves := make([]RBNode[K, V], 0, size>>1+1) 84 stack := make([]RBNode[K, V], 0, size>>1) 85 defer func() { 86 clear(stack) 87 }() 88 stack = append(stack, aux) 89 90 for len(stack) > 0 { 91 aux = stack[0] 92 l, r := aux.Left(), aux.Right() 93 if /* nil leaves, keep one */ isNilLeaf[K, V](l) || isNilLeaf[K, V](r) { 94 leaves = append(leaves, aux) 95 } 96 if !isNilLeaf[K, V](l) { 97 stack = append(stack, l) 98 } 99 if !isNilLeaf[K, V](r) { 100 stack = append(stack, r) 101 } 102 stack = stack[1:] 103 } 104 return leaves 105 } 106 107 /* 108 <X> is a RED node. 109 [X] is a BLACK node (or NIL). 110 111 [13] 112 / \ 113 <8> [15] 114 / \ / \ 115 [6] [11] [14] [17] 116 / / 117 <1> [16] 118 119 2-3-4 tree like: 120 121 <8> --- [13] --- <15> 122 / \ / \ 123 / \ / \ 124 <1>-[6][11] [14] <16>-[17] 125 126 Each leaf node to root node black depth are equal. 127 */ 128 func BlackViolationValidate[K infra.OrderedKey, V any](tree RBTree[K, V]) error { 129 leaves := bfsLeaves[K, V](tree) 130 if leaves == nil { 131 return nil 132 } 133 134 blackDepth := blackDepthTo[K, V](leaves[0], tree.Root()) 135 for i := 1; i < len(leaves); i++ { 136 if blackDepthTo[K, V](leaves[i], tree.Root()) != blackDepth { 137 return errors.New("rbtree black violation") 138 } 139 } 140 return nil 141 }