Skip to content

Commit 00c0d6f

Browse files
committed
AVL tree implementation
1 parent c93985e commit 00c0d6f

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

BinarySearchTrees/AVLmap.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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

Comments
 (0)