1+ import TreeMap
2+
3+ class AVLTree (TreeMap ):
4+ """ Sorted map implementation using an AVL tree """
5+
6+ # nested _Node class
7+
8+ class _Node (TreeMap ._Node ):
9+ """Node class for AVL maintains height value for balancing """
10+
11+ __slots__ = '_height' #additional data member to store height
12+
13+ def __init__ (self , element , parent = None , left = None , right = None ):
14+ super ().__init__ (element , parent , left , right )
15+ self ._height = 0 # willl be recomputed during balancing
16+
17+ def left_height (self ):
18+ return self ._left ._height if self ._left is not None else 0
19+
20+ def right_height (self ):
21+ return self ._right ._height if self ._right is not None else 0
22+
23+ # positional based utility methods
24+
25+ def _recompute_height (self , p ):
26+ p ._node ._height = 1 + max (p ._node .left_height (), p ._node .right_height ())
27+
28+ def _isbalanced (self ,p ):
29+ return abs (p ._node .left_height () - p ._node .right_height ()) <= 1
30+
31+ def _tall_child (self , p , favorleft = False ): #parameter controls tiebreaker
32+ """if there is a tie in height of children on node y, x (child) will be
33+ the child on the same side as the node y from the parent of y perspective.
34+ If one child is talled than the other x will be that taller child"""
35+
36+ if p ._node .left_height () + (1 if favorleft else 0 ) > p ._node .right_height ():
37+ return self .left (p )
38+ else :
39+ return self .right (p )
40+
41+ def _tall_grandchild (self , p ):
42+ child = self ._tall_child (p )
43+ # if child is on left, favor left; else favor right grandchild
44+
45+ alignment = (child == self .left (p ))
46+
47+ return self ._tall_child (child , alignment )
48+
49+ def _rebalance (self , p ):
50+ while p is not None :
51+ old_height = p ._node ._height #trivially 0 is new node
52+
53+ if not self ._isbalanced (p ): #imbalance detected
54+ #perform trinode restructuring, setting p to resulting root
55+ #and recompute new local heights after the restructure
56+ p = self .restructure (self ._tall_grandchild (p ))
57+ self ._recompute_height (self ._left (p ))
58+ self ._recompute_height (self .right (p ))
59+
60+ self ._recompute_height (p ) #adjust for recent changes
61+ if p ._node ._height == old_height : # has height changed ?
62+ p = None #no further changes
63+ else :
64+ p = self .parent (p ) #repeat with parent
65+
66+ def _rebalance_insert (self ,p ):
67+ self ._rebalance (p )
68+
69+ def _rebalance_delete (self ,p ):
70+ self ._rebalance (p )
0 commit comments