2
2
python/black : true
3
3
flake8 : passed
4
4
"""
5
+ from typing import Iterator , Optional
5
6
6
7
7
8
class RedBlackTree :
@@ -18,7 +19,14 @@ class RedBlackTree:
18
19
terms of the size of the tree.
19
20
"""
20
21
21
- def __init__ (self , label = None , color = 0 , parent = None , left = None , right = None ):
22
+ def __init__ (
23
+ self ,
24
+ label : Optional [int ] = None ,
25
+ color : int = 0 ,
26
+ parent : Optional ["RedBlackTree" ] = None ,
27
+ left : Optional ["RedBlackTree" ] = None ,
28
+ right : Optional ["RedBlackTree" ] = None ,
29
+ ) -> None :
22
30
"""Initialize a new Red-Black Tree node with the given values:
23
31
label: The value associated with this node
24
32
color: 0 if black, 1 if red
@@ -34,7 +42,7 @@ def __init__(self, label=None, color=0, parent=None, left=None, right=None):
34
42
35
43
# Here are functions which are specific to red-black trees
36
44
37
- def rotate_left (self ):
45
+ def rotate_left (self ) -> "RedBlackTree" :
38
46
"""Rotate the subtree rooted at this node to the left and
39
47
returns the new root to this subtree.
40
48
Performing one rotation can be done in O(1).
@@ -54,7 +62,7 @@ def rotate_left(self):
54
62
right .parent = parent
55
63
return right
56
64
57
- def rotate_right (self ):
65
+ def rotate_right (self ) -> "RedBlackTree" :
58
66
"""Rotate the subtree rooted at this node to the right and
59
67
returns the new root to this subtree.
60
68
Performing one rotation can be done in O(1).
@@ -74,7 +82,7 @@ def rotate_right(self):
74
82
left .parent = parent
75
83
return left
76
84
77
- def insert (self , label ) :
85
+ def insert (self , label : int ) -> "RedBlackTree" :
78
86
"""Inserts label into the subtree rooted at self, performs any
79
87
rotations necessary to maintain balance, and then returns the
80
88
new root to this subtree (likely self).
@@ -100,7 +108,7 @@ def insert(self, label):
100
108
self .right ._insert_repair ()
101
109
return self .parent or self
102
110
103
- def _insert_repair (self ):
111
+ def _insert_repair (self ) -> None :
104
112
"""Repair the coloring from inserting into a tree."""
105
113
if self .parent is None :
106
114
# This node is the root, so it just needs to be black
@@ -131,7 +139,7 @@ def _insert_repair(self):
131
139
self .grandparent .color = 1
132
140
self .grandparent ._insert_repair ()
133
141
134
- def remove (self , label ) :
142
+ def remove (self , label : int ) -> "RedBlackTree" :
135
143
"""Remove label from this tree."""
136
144
if self .label == label :
137
145
if self .left and self .right :
@@ -186,7 +194,7 @@ def remove(self, label):
186
194
self .right .remove (label )
187
195
return self .parent or self
188
196
189
- def _remove_repair (self ):
197
+ def _remove_repair (self ) -> None :
190
198
"""Repair the coloring of the tree that may have been messed up."""
191
199
if color (self .sibling ) == 1 :
192
200
self .sibling .color = 0
@@ -250,7 +258,7 @@ def _remove_repair(self):
250
258
self .parent .color = 0
251
259
self .parent .sibling .color = 0
252
260
253
- def check_color_properties (self ):
261
+ def check_color_properties (self ) -> bool :
254
262
"""Check the coloring of the tree, and return True iff the tree
255
263
is colored in a way which matches these five properties:
256
264
(wording stolen from wikipedia article)
@@ -287,7 +295,7 @@ def check_color_properties(self):
287
295
# All properties were met
288
296
return True
289
297
290
- def check_coloring (self ):
298
+ def check_coloring (self ) -> None :
291
299
"""A helper function to recursively check Property 4 of a
292
300
Red-Black Tree. See check_color_properties for more info.
293
301
"""
@@ -300,7 +308,7 @@ def check_coloring(self):
300
308
return False
301
309
return True
302
310
303
- def black_height (self ):
311
+ def black_height (self ) -> int :
304
312
"""Returns the number of black nodes from this node to the
305
313
leaves of the tree, or None if there isn't one such value (the
306
314
tree is color incorrectly).
@@ -322,14 +330,14 @@ def black_height(self):
322
330
323
331
# Here are functions which are general to all binary search trees
324
332
325
- def __contains__ (self , label ):
333
+ def __contains__ (self , label ) -> bool :
326
334
"""Search through the tree for label, returning True iff it is
327
335
found somewhere in the tree.
328
336
Guaranteed to run in O(log(n)) time.
329
337
"""
330
338
return self .search (label ) is not None
331
339
332
- def search (self , label ) :
340
+ def search (self , label : int ) -> "RedBlackTree" :
333
341
"""Search through the tree for label, returning its node if
334
342
it's found, and None otherwise.
335
343
This method is guaranteed to run in O(log(n)) time.
@@ -347,7 +355,7 @@ def search(self, label):
347
355
else :
348
356
return self .left .search (label )
349
357
350
- def floor (self , label ) :
358
+ def floor (self , label : int ) -> int :
351
359
"""Returns the largest element in this tree which is at most label.
352
360
This method is guaranteed to run in O(log(n)) time."""
353
361
if self .label == label :
@@ -364,7 +372,7 @@ def floor(self, label):
364
372
return attempt
365
373
return self .label
366
374
367
- def ceil (self , label ) :
375
+ def ceil (self , label : int ) -> int :
368
376
"""Returns the smallest element in this tree which is at least label.
369
377
This method is guaranteed to run in O(log(n)) time.
370
378
"""
@@ -382,7 +390,7 @@ def ceil(self, label):
382
390
return attempt
383
391
return self .label
384
392
385
- def get_max (self ):
393
+ def get_max (self ) -> int :
386
394
"""Returns the largest element in this tree.
387
395
This method is guaranteed to run in O(log(n)) time.
388
396
"""
@@ -392,7 +400,7 @@ def get_max(self):
392
400
else :
393
401
return self .label
394
402
395
- def get_min (self ):
403
+ def get_min (self ) -> int :
396
404
"""Returns the smallest element in this tree.
397
405
This method is guaranteed to run in O(log(n)) time.
398
406
"""
@@ -403,15 +411,15 @@ def get_min(self):
403
411
return self .label
404
412
405
413
@property
406
- def grandparent (self ):
414
+ def grandparent (self ) -> "RedBlackTree" :
407
415
"""Get the current node's grandparent, or None if it doesn't exist."""
408
416
if self .parent is None :
409
417
return None
410
418
else :
411
419
return self .parent .parent
412
420
413
421
@property
414
- def sibling (self ):
422
+ def sibling (self ) -> "RedBlackTree" :
415
423
"""Get the current node's sibling, or None if it doesn't exist."""
416
424
if self .parent is None :
417
425
return None
@@ -420,18 +428,18 @@ def sibling(self):
420
428
else :
421
429
return self .parent .left
422
430
423
- def is_left (self ):
431
+ def is_left (self ) -> bool :
424
432
"""Returns true iff this node is the left child of its parent."""
425
433
return self .parent and self .parent .left is self
426
434
427
- def is_right (self ):
435
+ def is_right (self ) -> bool :
428
436
"""Returns true iff this node is the right child of its parent."""
429
437
return self .parent and self .parent .right is self
430
438
431
- def __bool__ (self ):
439
+ def __bool__ (self ) -> bool :
432
440
return True
433
441
434
- def __len__ (self ):
442
+ def __len__ (self ) -> int :
435
443
"""
436
444
Return the number of nodes in this tree.
437
445
"""
@@ -442,28 +450,28 @@ def __len__(self):
442
450
ln += len (self .right )
443
451
return ln
444
452
445
- def preorder_traverse (self ):
453
+ def preorder_traverse (self ) -> Iterator [ int ] :
446
454
yield self .label
447
455
if self .left :
448
456
yield from self .left .preorder_traverse ()
449
457
if self .right :
450
458
yield from self .right .preorder_traverse ()
451
459
452
- def inorder_traverse (self ):
460
+ def inorder_traverse (self ) -> Iterator [ int ] :
453
461
if self .left :
454
462
yield from self .left .inorder_traverse ()
455
463
yield self .label
456
464
if self .right :
457
465
yield from self .right .inorder_traverse ()
458
466
459
- def postorder_traverse (self ):
467
+ def postorder_traverse (self ) -> Iterator [ int ] :
460
468
if self .left :
461
469
yield from self .left .postorder_traverse ()
462
470
if self .right :
463
471
yield from self .right .postorder_traverse ()
464
472
yield self .label
465
473
466
- def __repr__ (self ):
474
+ def __repr__ (self ) -> str :
467
475
from pprint import pformat
468
476
469
477
if self .left is None and self .right is None :
@@ -476,15 +484,15 @@ def __repr__(self):
476
484
indent = 1 ,
477
485
)
478
486
479
- def __eq__ (self , other ):
487
+ def __eq__ (self , other ) -> bool :
480
488
"""Test if two trees are equal."""
481
489
if self .label == other .label :
482
490
return self .left == other .left and self .right == other .right
483
491
else :
484
492
return False
485
493
486
494
487
- def color (node ):
495
+ def color (node ) -> int :
488
496
"""Returns the color of a node, allowing for None leaves."""
489
497
if node is None :
490
498
return 0
@@ -498,7 +506,7 @@ def color(node):
498
506
"""
499
507
500
508
501
- def test_rotations ():
509
+ def test_rotations () -> bool :
502
510
"""Test that the rotate_left and rotate_right functions work."""
503
511
# Make a tree to test on
504
512
tree = RedBlackTree (0 )
@@ -534,7 +542,7 @@ def test_rotations():
534
542
return True
535
543
536
544
537
- def test_insertion_speed ():
545
+ def test_insertion_speed () -> bool :
538
546
"""Test that the tree balances inserts to O(log(n)) by doing a lot
539
547
of them.
540
548
"""
@@ -544,7 +552,7 @@ def test_insertion_speed():
544
552
return True
545
553
546
554
547
- def test_insert ():
555
+ def test_insert () -> bool :
548
556
"""Test the insert() method of the tree correctly balances, colors,
549
557
and inserts.
550
558
"""
@@ -565,7 +573,7 @@ def test_insert():
565
573
return tree == ans
566
574
567
575
568
- def test_insert_and_search ():
576
+ def test_insert_and_search () -> bool :
569
577
"""Tests searching through the tree for values."""
570
578
tree = RedBlackTree (0 )
571
579
tree .insert (8 )
@@ -583,7 +591,7 @@ def test_insert_and_search():
583
591
return True
584
592
585
593
586
- def test_insert_delete ():
594
+ def test_insert_delete () -> bool :
587
595
"""Test the insert() and delete() method of the tree, verifying the
588
596
insertion and removal of elements, and the balancing of the tree.
589
597
"""
@@ -607,7 +615,7 @@ def test_insert_delete():
607
615
return True
608
616
609
617
610
- def test_floor_ceil ():
618
+ def test_floor_ceil () -> bool :
611
619
"""Tests the floor and ceiling functions in the tree."""
612
620
tree = RedBlackTree (0 )
613
621
tree .insert (- 16 )
@@ -623,7 +631,7 @@ def test_floor_ceil():
623
631
return True
624
632
625
633
626
- def test_min_max ():
634
+ def test_min_max () -> bool :
627
635
"""Tests the min and max functions in the tree."""
628
636
tree = RedBlackTree (0 )
629
637
tree .insert (- 16 )
@@ -637,7 +645,7 @@ def test_min_max():
637
645
return True
638
646
639
647
640
- def test_tree_traversal ():
648
+ def test_tree_traversal () -> bool :
641
649
"""Tests the three different tree traversal functions."""
642
650
tree = RedBlackTree (0 )
643
651
tree = tree .insert (- 16 )
@@ -655,7 +663,7 @@ def test_tree_traversal():
655
663
return True
656
664
657
665
658
- def test_tree_chaining ():
666
+ def test_tree_chaining () -> bool :
659
667
"""Tests the three different tree chaining functions."""
660
668
tree = RedBlackTree (0 )
661
669
tree = tree .insert (- 16 ).insert (16 ).insert (8 ).insert (24 ).insert (20 ).insert (22 )
@@ -672,7 +680,7 @@ def print_results(msg: str, passes: bool) -> None:
672
680
print (str (msg ), "works!" if passes else "doesn't work :(" )
673
681
674
682
675
- def pytests ():
683
+ def pytests () -> None :
676
684
assert test_rotations ()
677
685
assert test_insert ()
678
686
assert test_insert_and_search ()
@@ -682,7 +690,7 @@ def pytests():
682
690
assert test_tree_chaining ()
683
691
684
692
685
- def main ():
693
+ def main () -> None :
686
694
"""
687
695
>>> pytests()
688
696
"""
0 commit comments