1 Attribute VB_Name = "Rbt"
4 ' red-black tree algorithm, object method
6 Private Sentinel As CRbt ' all leafs are sentinels
7 Private Root As CRbt ' root of red-black tree
8 Private LastFind As CRbt ' last node found
11 Private Function FindNode(ByVal Key As Variant) As CRbt
13 ' Key ' designates key to find
17 ' Search tree for designated key, and return index to node.
23 ' find node specified by key
25 Do While Not current Is Sentinel
26 If current.Key = Key Then
27 Set FindNode = current
30 If Key < current.Key Then
31 Set current = current.Left
33 Set current = current.Right
37 Err.Raise errKeyNotFound, "Rbt.FindNode"
40 Private Sub RotateLeft(ByRef x As CRbt)
44 ' perform a left tree rotation about "x"
48 ' rotate node x to left
52 ' establish x.Right link
54 If Not y.Left Is Sentinel Then Set y.Left.Parent = x
56 ' establish y.Parent link
57 If Not y Is Sentinel Then Set y.Parent = x.Parent
58 If Not x.Parent Is Nothing Then
59 If x Is x.Parent.Left Then
62 Set x.Parent.Right = y
70 If Not x Is Sentinel Then Set x.Parent = y
73 Private Sub RotateRight(ByRef x As CRbt)
77 ' perform a right tree rotation about "x"
81 ' rotate node x to right
85 ' establish x.Left link
87 If Not y.Right Is Sentinel Then Set y.Right.Parent = x
89 ' establish y.parent link
90 If Not y Is Sentinel Then Set y.Parent = x.Parent
91 If Not x.Parent Is Nothing Then
92 If x Is x.Parent.Right Then
93 Set x.Parent.Right = y
103 If Not x Is Sentinel Then Set x.Parent = y
106 Private Sub InsertFixup(ByRef x As CRbt)
110 ' maintains red-black tree properties after inserting node x
114 ' maintain Red-Black tree balance
115 ' after inserting node x
117 ' check Red-Black properties
118 Do While (Not x Is Root)
119 If x.Parent.Color <> Red Then Exit Do
120 ' we have a violation
121 If x.Parent Is x.Parent.Parent.Left Then
122 Set y = x.Parent.Parent.Right
123 If y.Color = Red Then
126 x.Parent.Color = Black
128 x.Parent.Parent.Color = Red
129 Set x = x.Parent.Parent
133 If x Is x.Parent.Right Then
134 ' make x a left child
140 x.Parent.Color = Black
141 x.Parent.Parent.Color = Red
142 RotateRight x.Parent.Parent
146 ' mirror image of above code
147 Set y = x.Parent.Parent.Left
148 If y.Color = Red Then
151 x.Parent.Color = Black
153 x.Parent.Parent.Color = Red
154 Set x = x.Parent.Parent
158 If x Is x.Parent.Left Then
162 x.Parent.Color = Black
163 x.Parent.Parent.Color = Red
164 RotateLeft x.Parent.Parent
171 Public Sub Insert(ByVal KeyVal As Variant, ByRef RecVal As Variant)
173 ' KeyVal key of node to insert
174 ' RecVal record associated with key
176 ' Inserts record RecVal with key KeyVal.
184 ' allocate node for data and insert in tree
186 ' find where node belongs
189 Do While Not current Is Sentinel
190 If current.Key = KeyVal Then Raise errDuplicateKey, "Rbt.Insert"
192 If KeyVal < current.Key Then
193 Set current = current.Left
195 Set current = current.Right
201 Set x.Parent = Parent
202 Set x.Left = Sentinel
203 Set x.Right = Sentinel
206 ' copy fields to node
210 ' insert node in tree
211 If Not Parent Is Nothing Then
212 If KeyVal < Parent.Key Then
222 Set LastFind = Sentinel
225 Private Sub DeleteFixup(ByRef x As CRbt)
229 ' maintains red-black tree properties after deleting a node
233 ' maintain Red-Black tree balance
234 ' after deleting node x
236 Do While Not x Is Root
237 If x.Color <> Black Then Exit Do
238 If x Is x.Parent.Left Then
239 Set w = x.Parent.Right
240 If w.Color = Red Then
244 Set w = x.Parent.Right
246 If w.Left.Color = Black And w.Right.Color = Black Then
250 If w.Right.Color = Black Then
254 Set w = x.Parent.Right
256 w.Color = x.Parent.Color
257 x.Parent.Color = Black
258 w.Right.Color = Black
263 Set w = x.Parent.Left
264 If w.Color = Red Then
268 Set w = x.Parent.Left
270 If w.Right.Color = Black And w.Left.Color = Black Then
274 If w.Left.Color = Black Then
275 w.Right.Color = Black
278 Set w = x.Parent.Left
280 w.Color = x.Parent.Color
281 x.Parent.Color = Black
291 Public Sub Delete(ByVal KeyVal As Variant)
293 ' KeyVal key of node to delete
295 ' Deletes record with key KeyVal.
303 If Not LastFind Is Sentinel Then
304 If LastFind.Rec = KeyVal Then
307 Set z = FindNode(KeyVal)
310 Set z = FindNode(KeyVal)
313 ' delete node z from tree
314 If z.Left Is Sentinel Or z.Right Is Sentinel Then
315 ' y has a Sentinel node as a child
318 ' find tree successor with a Sentinel node as a child
320 Do While Not y.Left Is Sentinel
325 ' x is y's only child, and x may be a sentinel node
326 If Not y.Left Is Sentinel Then
332 ' remove y from the parent chain
333 Set x.Parent = y.Parent
334 If Not y.Parent Is Nothing Then
335 If y Is y.Parent.Left Then
336 Set y.Parent.Left = x
338 Set y.Parent.Right = x
344 ' copy data fields from y to z
350 ' if we removed a black node, we need to do some fixup
351 If y.Color = Black Then DeleteFixup x
353 ' y is freed automatically, as it's no longer referenced
355 Set LastFind = Sentinel
358 Public Function Find(ByVal KeyVal) As Variant
360 ' KeyVal key of node to delete
362 ' record associated with key
364 ' Finds record with key KeyVal
368 Set LastFind = FindNode(KeyVal)
376 Set Sentinel = New CRbt
377 Set Sentinel.Left = Sentinel
378 Set Sentinel.Right = Sentinel
379 Set Sentinel.Parent = Nothing
380 Sentinel.Color = Black
382 Set LastFind = Sentinel
385 Private Sub ZapNode(x As CRbt)
389 ' recursively set all parent pointers to Nothing
391 If x Is Nothing Then Exit Sub
392 Set x.Parent = Nothing
402 Set Sentinel.Left = Nothing
403 Set Sentinel.Right = Nothing
404 Set Sentinel.Parent = Nothing
405 Set Sentinel = Nothing
407 ' remove all parent pointers
411 ' now, freeing root will free whole tree