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  }