github.com/benz9527/toy-box/algo@v0.0.0-20240221120937-66c0c6bd5abd/tree/redblack_tree.go (about)

     1  package tree
     2  
     3  import "fmt"
     4  
     5  const RED int = 1
     6  const BLACK int = 0
     7  
     8  type RedBlackNode struct {
     9  	Item                int
    10  	Color               int
    11  	Parent, Left, Right *RedBlackNode
    12  }
    13  
    14  // EmptyNil All value is default nil(zero) value
    15  var EmptyNil *RedBlackNode = nil
    16  
    17  type RedBlackTree struct {
    18  	Root *RedBlackNode
    19  }
    20  
    21  func (rbTree *RedBlackTree) PreOrder(n *RedBlackNode) {
    22  	if n != EmptyNil {
    23  		fmt.Print(n.Item, " ")
    24  		rbTree.PreOrder(n.Left)
    25  		rbTree.PreOrder(n.Right)
    26  	}
    27  }
    28  
    29  func (rbTree *RedBlackTree) InOrder(n *RedBlackNode) {
    30  	if n != EmptyNil {
    31  		rbTree.InOrder(n.Left)
    32  		fmt.Print(n.Item, " ")
    33  		rbTree.InOrder(n.Right)
    34  	}
    35  }
    36  
    37  func (rbTree *RedBlackTree) PostOrder(n *RedBlackNode) {
    38  	if n != EmptyNil {
    39  		rbTree.PostOrder(n.Left)
    40  		rbTree.PostOrder(n.Right)
    41  		fmt.Print(n.Item, " ")
    42  	}
    43  }
    44  
    45  func (rbTree *RedBlackTree) Search(n *RedBlackNode, k int) *RedBlackNode {
    46  	if n == EmptyNil || k == n.Item {
    47  		return n
    48  	}
    49  
    50  	if k < n.Item {
    51  		return rbTree.Search(n.Left, k)
    52  	}
    53  	return rbTree.Search(n.Right, k)
    54  }
    55  
    56  func (rbTree *RedBlackTree) LeftRotate(nx *RedBlackNode) {
    57  	ny := nx.Right
    58  	nx.Right = ny.Left
    59  
    60  	if ny.Left != EmptyNil {
    61  		ny.Left.Parent = nx
    62  	}
    63  
    64  	ny.Parent = nx.Parent
    65  	if nx.Parent == nil {
    66  		rbTree.Root = ny
    67  	} else if nx == nx.Parent.Left {
    68  		nx.Parent.Left = ny
    69  	} else {
    70  		nx.Parent.Right = ny
    71  	}
    72  
    73  	ny.Left = nx
    74  	nx.Parent = ny
    75  }
    76  
    77  func (rbTree *RedBlackTree) RightRotate(nx *RedBlackNode) {
    78  	ny := nx.Left
    79  	nx.Left = ny.Right
    80  
    81  	if ny.Right != EmptyNil {
    82  		ny.Right.Parent = nx
    83  	}
    84  
    85  	ny.Parent = nx.Parent
    86  	if nx.Parent == nil {
    87  		rbTree.Root = ny
    88  	} else if nx == nx.Parent.Right {
    89  		nx.Parent.Right = ny
    90  	} else {
    91  		nx.Parent.Left = ny
    92  	}
    93  	ny.Right = nx
    94  	nx.Parent = ny
    95  }
    96  
    97  func (rbTree *RedBlackTree) Insert(k int) {
    98  	newNode := &RedBlackNode{
    99  		Parent: nil,
   100  		Item:   k,
   101  		Left:   EmptyNil,
   102  		Right:  EmptyNil,
   103  		Color:  RED,
   104  	}
   105  
   106  	var ny *RedBlackNode = nil
   107  	var nx = rbTree.Root
   108  
   109  	for nx != EmptyNil {
   110  		ny = nx
   111  		if newNode.Item < nx.Item {
   112  			nx = nx.Left
   113  		} else {
   114  			nx = nx.Right
   115  		}
   116  	}
   117  
   118  	newNode.Parent = ny
   119  	if ny == nil {
   120  		rbTree.Root = newNode
   121  	} else if newNode.Item < ny.Item {
   122  		ny.Left = newNode
   123  	} else {
   124  		ny.Right = newNode
   125  	}
   126  
   127  	if newNode.Parent == nil {
   128  		newNode.Color = BLACK
   129  		return
   130  	}
   131  
   132  	if newNode.Parent.Parent == nil {
   133  		return
   134  	}
   135  
   136  	rbTree.PostInsertBalance(newNode)
   137  }
   138  
   139  // PostInsertBalance Balance the node after insertion
   140  func (rbTree *RedBlackTree) PostInsertBalance(target *RedBlackNode) {
   141  	var tmp *RedBlackNode = nil
   142  	for target.Parent.Color == RED {
   143  		if target.Parent == target.Parent.Parent.Right {
   144  			tmp = target.Parent.Parent.Left
   145  			if tmp.Color == RED {
   146  				tmp.Color = BLACK
   147  				target.Parent.Color = BLACK
   148  				target.Parent.Parent.Color = RED
   149  				target = target.Parent.Parent
   150  			} else {
   151  				if target == target.Parent.Left {
   152  					target = target.Parent
   153  					rbTree.RightRotate(target)
   154  				}
   155  				target.Parent.Color = BLACK
   156  				target.Parent.Parent.Color = RED
   157  				rbTree.LeftRotate(target.Parent.Parent)
   158  			}
   159  		} else {
   160  			tmp = target.Parent.Parent.Right
   161  
   162  			if tmp.Color == RED {
   163  				tmp.Color = BLACK
   164  				target.Parent.Color = BLACK
   165  				target.Parent.Parent.Color = RED
   166  				target = target.Parent.Parent
   167  			} else {
   168  				if target == target.Parent.Right {
   169  					target = target.Parent
   170  					rbTree.LeftRotate(target)
   171  				}
   172  
   173  				target.Parent.Color = BLACK
   174  				target.Parent.Parent.Color = RED
   175  				rbTree.RightRotate(target.Parent.Parent)
   176  			}
   177  		}
   178  
   179  		if target == rbTree.Root {
   180  			break
   181  		}
   182  	}
   183  	rbTree.Root.Color = BLACK
   184  }
   185  
   186  func (rbTree *RedBlackTree) Transplant(currentNode, childNode *RedBlackNode) {
   187  	if currentNode.Parent == nil {
   188  		rbTree.Root = childNode
   189  	} else if currentNode == currentNode.Parent.Left {
   190  		currentNode.Parent.Left = childNode
   191  	} else {
   192  		currentNode.Parent.Right = childNode
   193  	}
   194  	childNode.Parent = currentNode.Parent
   195  }
   196  
   197  func (rbTree *RedBlackTree) Minimum(n *RedBlackNode) *RedBlackNode {
   198  	for n.Left != EmptyNil {
   199  		n = n.Left
   200  	}
   201  	return n
   202  }
   203  
   204  func (rbTree *RedBlackTree) Maximum(n *RedBlackNode) *RedBlackNode {
   205  	for n.Right != EmptyNil {
   206  		n = n.Right
   207  	}
   208  	return n
   209  }
   210  
   211  func (rbTree *RedBlackTree) Successor(nx *RedBlackNode) *RedBlackNode {
   212  	if nx.Right != EmptyNil {
   213  		return rbTree.Minimum(nx.Right)
   214  	}
   215  
   216  	ny := nx.Parent
   217  	for ny != EmptyNil &&
   218  		nx == ny.Right {
   219  		nx = ny
   220  		ny = ny.Parent
   221  	}
   222  	return ny
   223  }
   224  
   225  func (rbTree *RedBlackTree) Predecessor(nx *RedBlackNode) *RedBlackNode {
   226  	if nx.Left != EmptyNil {
   227  		return rbTree.Maximum(nx.Left)
   228  	}
   229  
   230  	ny := nx.Parent
   231  	for ny != EmptyNil &&
   232  		nx == ny.Left {
   233  		nx = ny
   234  		ny = ny.Parent
   235  	}
   236  	return ny
   237  }
   238  
   239  func (rbTree *RedBlackTree) Delete(parentNode *RedBlackNode, k int) {
   240  	nz := EmptyNil
   241  	var nx, ny *RedBlackNode = nil, nil
   242  	for parentNode != EmptyNil {
   243  		if parentNode.Item == k {
   244  			nz = parentNode
   245  		}
   246  
   247  		if parentNode.Item <= k {
   248  			parentNode = parentNode.Right
   249  		} else {
   250  			parentNode = parentNode.Left
   251  		}
   252  	}
   253  
   254  	if nz == EmptyNil {
   255  		fmt.Println("Could not find key in the tree!")
   256  		return
   257  	}
   258  
   259  	ny = nz
   260  	nyOldColor := ny.Color
   261  	if nz.Left == EmptyNil {
   262  		nx = nz.Right
   263  		rbTree.Transplant(nz, nz.Right)
   264  	} else if nz.Right == EmptyNil {
   265  		nx = nz.Left
   266  		rbTree.Transplant(nz, nz.Left)
   267  	} else {
   268  		ny = rbTree.Minimum(nz.Right)
   269  		nyOldColor = ny.Color
   270  		nx = ny.Right
   271  		if ny.Parent == nz {
   272  			nx.Parent = ny
   273  		} else {
   274  			rbTree.Transplant(ny, ny.Right)
   275  			ny.Right = nz.Right
   276  			ny.Right.Parent = ny
   277  		}
   278  
   279  		rbTree.Transplant(nz, ny)
   280  		ny.Left = nz.Left
   281  		ny.Left.Parent = ny
   282  		ny.Color = nz.Color
   283  	}
   284  
   285  	if nyOldColor == BLACK {
   286  		rbTree.PostDeleteBalance(nx)
   287  	}
   288  }
   289  
   290  // PostDeleteBalance Balance the tree after deletion of a node
   291  func (rbTree *RedBlackTree) PostDeleteBalance(nx *RedBlackNode) {
   292  	var ns *RedBlackNode = nil
   293  	for nx != rbTree.Root &&
   294  		nx.Color == BLACK {
   295  		if nx == nx.Parent.Left {
   296  			ns = nx.Parent.Right
   297  			if ns.Color == RED {
   298  				ns.Color = BLACK
   299  				nx.Parent.Color = RED
   300  				rbTree.LeftRotate(nx.Parent)
   301  				ns = nx.Parent.Right
   302  			}
   303  
   304  			if ns.Left.Color == BLACK &&
   305  				ns.Right.Color == BLACK {
   306  				ns.Color = RED
   307  				nx = nx.Parent
   308  			} else {
   309  				if ns.Right.Color == BLACK {
   310  					ns.Left.Color = BLACK
   311  					ns.Color = RED
   312  					rbTree.RightRotate(ns)
   313  					ns = nx.Parent.Right
   314  				}
   315  
   316  				ns.Color = nx.Parent.Color
   317  				nx.Parent.Color = BLACK
   318  				ns.Right.Color = BLACK
   319  				rbTree.LeftRotate(nx.Parent)
   320  				nx = rbTree.Root
   321  			}
   322  		} else {
   323  			ns = nx.Parent.Left
   324  			if ns.Color == RED {
   325  				ns.Color = BLACK
   326  				nx.Parent.Color = RED
   327  				rbTree.RightRotate(nx.Parent)
   328  				ns = nx.Parent.Left
   329  			}
   330  
   331  			if ns.Left.Color == BLACK &&
   332  				ns.Right.Color == BLACK {
   333  				ns.Color = RED
   334  				nx = nx.Parent
   335  			} else {
   336  				if ns.Left.Color == BLACK {
   337  					ns.Right.Color = BLACK
   338  					ns.Color = RED
   339  					rbTree.LeftRotate(ns)
   340  					ns = nx.Parent.Left
   341  				}
   342  
   343  				ns.Color = nx.Parent.Color
   344  				nx.Parent.Color = BLACK
   345  				ns.Left.Color = BLACK
   346  				rbTree.RightRotate(nx.Parent)
   347  				nx = rbTree.Root
   348  			}
   349  		}
   350  	}
   351  	nx.Color = BLACK
   352  }