Skip to content

Commit c8747af

Browse files
authored
Update red_black_tree.py
1 parent c7d9326 commit c8747af

File tree

1 file changed

+50
-18
lines changed

1 file changed

+50
-18
lines changed

data_structures/binary_tree/red_black_tree.py

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -336,24 +336,33 @@ def _remove_repair(self) -> None:
336336
self.parent.sibling.color = 0
337337

338338
def check_color_properties(self) -> bool:
339-
"""Check if the tree satisfies all Red-Black tree properties.
339+
def check_color_properties(self) -> bool:
340+
"""
341+
Verify that all Red-Black Tree properties are satisfied:
342+
1. Root node is black
343+
2. No two consecutive red nodes (red node cannot have red children)
344+
3. All paths from any node to its leaf descendants have the same number of black nodes
340345
341346
Returns:
342347
True if all properties are satisfied, False otherwise
343348
344349
Examples:
345-
>>> tree = RedBlackTree(0)
346-
>>> tree = tree.insert(1).insert(-1)
350+
>>> tree = RedBlackTree(10).insert(5).insert(15)
347351
>>> tree.check_color_properties()
348352
True
353+
>>> tree.left.color = 1 # Force invalid state: two consecutive reds
354+
>>> tree.check_color_properties()
355+
False
349356
"""
350-
# Property 2
351-
if self.color:
357+
# Property 1: Root must be black
358+
if self.parent is None and self.color != 0:
352359
return False
353-
# Property 4
360+
361+
# Property 2: No two consecutive red nodes
354362
if not self.check_coloring():
355363
return False
356-
# Property 5
364+
365+
# Property 3: All paths have same black height
357366
return self.black_height() is not None
358367

359368
def check_coloring(self) -> bool:
@@ -364,18 +373,41 @@ def check_coloring(self) -> bool:
364373
return False
365374
return not (self.right and not self.right.check_coloring())
366375

367-
def black_height(self) -> int | None:
368-
"""Calculate the black height of the tree."""
369-
if self is None or self.left is None or self.right is None:
370-
return 1
371-
left = RedBlackTree.black_height(self.left)
372-
right = RedBlackTree.black_height(self.right)
373-
if left is None or right is None:
374-
return None
375-
if left != right:
376-
return None
377-
return left + (1 - self.color)
376+
def black_height(self) -> int | None:
377+
"""
378+
Calculate the black height of the tree and verify consistency
379+
- Black height = number of black nodes from current node to any leaf
380+
- Count includes current node if black and all leaf nodes (None are black)
381+
- Returns None if any path has different black height
378382
383+
Returns:
384+
Black height if consistent, None otherwise
385+
386+
Examples:
387+
>>> tree = RedBlackTree(10, color=0) # Black root
388+
>>> tree.insert(5, color=1) # Red child
389+
>>> tree.black_height() # Paths: [10(black), 5(red), None(black)] = 2
390+
2 [10(black), None(black)] = 2
391+
"""
392+
# Base case: Leaf node (None is always black)
393+
if self is None:
394+
return 1
395+
396+
# Leaf node case (both children are None)
397+
if self.left is None and self.right is None:
398+
# Count: current node (if black) + leaf (black)
399+
return 1 + (1 - self.color) # 2 if black, 1 if red
400+
401+
# Recursive case: Check both subtrees
402+
left_bh = self.left.black_height() if self.left else 1
403+
right_bh = self.right.black_height() if self.right else 1
404+
405+
# Validate consistency
406+
if left_bh is None or right_bh is None or left_bh != right_bh:
407+
return None # Inconsistent black heights
408+
409+
# Current node's contribution: add 1 if black
410+
return left_bh + (1 - self.color)
379411
def __contains__(self, label: int) -> bool:
380412
"""Check if the tree contains a label.
381413

0 commit comments

Comments
 (0)