1- """
2- Implementation of an auto-balanced binary tree!
3- For doctests run following command:
4- python3 -m doctest -v avl_tree.py
5- For testing run:
6- python avl_tree.py
7- """
8-
91from __future__ import annotations
102
113import math
@@ -24,21 +16,13 @@ def is_empty(self) -> bool:
2416
2517 def push (self , data : Any ) -> None :
2618 self .data .append (data )
27- self .tail = self . tail + 1
19+ self .tail += 1
2820
2921 def pop (self ) -> Any :
3022 ret = self .data [self .head ]
31- self .head = self . head + 1
23+ self .head += 1
3224 return ret
3325
34- def count (self ) -> int :
35- return self .tail - self .head
36-
37- def print_queue (self ) -> None :
38- print (self .data )
39- print ("**************" )
40- print (self .data [self .head : self .tail ])
41-
4226
4327class MyNode :
4428 def __init__ (self , data : Any ) -> None :
@@ -59,9 +43,6 @@ def get_right(self) -> MyNode | None:
5943 def get_height (self ) -> int :
6044 return self .height
6145
62- def set_data (self , data : Any ) -> None :
63- self .data = data
64-
6546 def set_left (self , node : MyNode | None ) -> None :
6647 self .left = node
6748
@@ -73,277 +54,112 @@ def set_height(self, height: int) -> None:
7354
7455
7556def get_height (node : MyNode | None ) -> int :
76- if node is None :
77- return 0
78- return node .get_height ()
57+ return node .get_height () if node else 0
7958
8059
8160def my_max (a : int , b : int ) -> int :
82- if a > b :
83- return a
84- return b
61+ return a if a > b else b
8562
8663
8764def right_rotation (node : MyNode ) -> MyNode :
88- r"""
89- A B
90- / \ / \
91- B C Bl A
92- / \ --> / / \
93- Bl Br UB Br C
94- /
95- UB
96- UB = unbalanced node
97- """
98- print ("left rotation node:" , node .get_data ())
9965 ret = node .get_left ()
10066 assert ret is not None
10167 node .set_left (ret .get_right ())
10268 ret .set_right (node )
103- h1 = my_max ( get_height ( node . get_right ()), get_height ( node . get_left ())) + 1
104- node .set_height (h1 )
105- h2 = my_max (get_height (ret .get_right ()), get_height (ret .get_left ())) + 1
106- ret . set_height ( h2 )
69+
70+ node .set_height (my_max ( get_height ( node . get_left ()), get_height ( node . get_right ())) + 1 )
71+ ret . set_height ( my_max (get_height (ret .get_left ()), get_height (ret .get_right ())) + 1 )
72+
10773 return ret
10874
10975
11076def left_rotation (node : MyNode ) -> MyNode :
111- """
112- a mirror symmetry rotation of the left_rotation
113- """
114- print ("right rotation node:" , node .get_data ())
11577 ret = node .get_right ()
11678 assert ret is not None
11779 node .set_right (ret .get_left ())
11880 ret .set_left (node )
119- h1 = my_max ( get_height ( node . get_right ()), get_height ( node . get_left ())) + 1
120- node .set_height (h1 )
121- h2 = my_max (get_height (ret .get_right ()), get_height (ret .get_left ())) + 1
122- ret . set_height ( h2 )
81+
82+ node .set_height (my_max ( get_height ( node . get_left ()), get_height ( node . get_right ())) + 1 )
83+ ret . set_height ( my_max (get_height (ret .get_left ()), get_height (ret .get_right ())) + 1 )
84+
12385 return ret
12486
12587
12688def lr_rotation (node : MyNode ) -> MyNode :
127- r"""
128- A A Br
129- / \ / \ / \
130- B C LR Br C RR B A
131- / \ --> / \ --> / / \
132- Bl Br B UB Bl UB C
133- \ /
134- UB Bl
135- RR = right_rotation LR = left_rotation
136- """
137- left_child = node .get_left ()
138- assert left_child is not None
139- node .set_left (left_rotation (left_child ))
89+ node .set_left (left_rotation (node .get_left ()))
14090 return right_rotation (node )
14191
14292
14393def rl_rotation (node : MyNode ) -> MyNode :
144- right_child = node .get_right ()
145- assert right_child is not None
146- node .set_right (right_rotation (right_child ))
94+ node .set_right (right_rotation (node .get_right ()))
14795 return left_rotation (node )
14896
14997
150- def insert_node (node : MyNode | None , data : Any ) -> MyNode | None :
98+ def insert_node (node : MyNode | None , data : Any ) -> MyNode :
15199 if node is None :
152100 return MyNode (data )
101+
153102 if data < node .get_data ():
154103 node .set_left (insert_node (node .get_left (), data ))
155- if (
156- get_height (node .get_left ()) - get_height (node .get_right ()) == 2
157- ): # an unbalance detected
104+
105+ if get_height (node .get_left ()) - get_height (node .get_right ()) == 2 :
158106 left_child = node .get_left ()
159- assert left_child is not None
160- if (
161- data < left_child .get_data ()
162- ): # new node is the left child of the left child
107+ if data < left_child .get_data ():
163108 node = right_rotation (node )
164109 else :
165110 node = lr_rotation (node )
111+
166112 else :
167113 node .set_right (insert_node (node .get_right (), data ))
114+
168115 if get_height (node .get_right ()) - get_height (node .get_left ()) == 2 :
169116 right_child = node .get_right ()
170- assert right_child is not None
171117 if data < right_child .get_data ():
172118 node = rl_rotation (node )
173119 else :
174120 node = left_rotation (node )
175- h1 = my_max (get_height (node .get_right ()), get_height (node .get_left ())) + 1
176- node .set_height (h1 )
177- return node
178121
179-
180- def get_right_most (root : MyNode ) -> Any :
181- while True :
182- right_child = root .get_right ()
183- if right_child is None :
184- break
185- root = right_child
186- return root .get_data ()
187-
188-
189- def get_left_most (root : MyNode ) -> Any :
190- while True :
191- left_child = root .get_left ()
192- if left_child is None :
193- break
194- root = left_child
195- return root .get_data ()
196-
197-
198- def del_node (root : MyNode , data : Any ) -> MyNode | None :
199- left_child = root .get_left ()
200- right_child = root .get_right ()
201- if root .get_data () == data :
202- if left_child is not None and right_child is not None :
203- temp_data = get_left_most (right_child )
204- root .set_data (temp_data )
205- root .set_right (del_node (right_child , temp_data ))
206- elif left_child is not None :
207- root = left_child
208- elif right_child is not None :
209- root = right_child
210- else :
211- return None
212- elif root .get_data () > data :
213- if left_child is None :
214- print ("No such data" )
215- return root
216- else :
217- root .set_left (del_node (left_child , data ))
218- # root.get_data() < data
219- elif right_child is None :
220- return root
221- else :
222- root .set_right (del_node (right_child , data ))
223-
224- # Re-fetch left_child and right_child references
225- left_child = root .get_left ()
226- right_child = root .get_right ()
227-
228- if get_height (right_child ) - get_height (left_child ) == 2 :
229- assert right_child is not None
230- if get_height (right_child .get_right ()) > get_height (right_child .get_left ()):
231- root = left_rotation (root )
232- else :
233- root = rl_rotation (root )
234- elif get_height (right_child ) - get_height (left_child ) == - 2 :
235- assert left_child is not None
236- if get_height (left_child .get_left ()) > get_height (left_child .get_right ()):
237- root = right_rotation (root )
238- else :
239- root = lr_rotation (root )
240- height = my_max (get_height (root .get_right ()), get_height (root .get_left ())) + 1
241- root .set_height (height )
242- return root
122+ node .set_height (my_max (get_height (node .get_left ()), get_height (node .get_right ())) + 1 )
123+ return node
243124
244125
245126class AVLtree :
246- """
247- An AVL tree doctest
248- Examples:
249- >>> t = AVLtree()
250- >>> t.insert(4)
251- insert:4
252- >>> print(str(t).replace(" \\ n","\\ n"))
253- 4
254- *************************************
255- >>> t.insert(2)
256- insert:2
257- >>> print(str(t).replace(" \\ n","\\ n").replace(" \\ n","\\ n"))
258- 4
259- 2 *
260- *************************************
261- >>> t.insert(3)
262- insert:3
263- right rotation node: 2
264- left rotation node: 4
265- >>> print(str(t).replace(" \\ n","\\ n").replace(" \\ n","\\ n"))
266- 3
267- 2 4
268- *************************************
269- >>> t.get_height()
270- 2
271- >>> t.del_node(3)
272- delete:3
273- >>> print(str(t).replace(" \\ n","\\ n").replace(" \\ n","\\ n"))
274- 4
275- 2 *
276- *************************************
277- """
278-
279127 def __init__ (self ) -> None :
280128 self .root : MyNode | None = None
281129
130+ def insert (self , data : Any ) -> None :
131+ self .root = insert_node (self .root , data )
132+
282133 def get_height (self ) -> int :
283134 return get_height (self .root )
284135
285- def insert (self , data : Any ) -> None :
286- print ("insert:" + str (data ))
287- self .root = insert_node (self .root , data )
288136
289- def del_node (self , data : Any ) -> None :
290- print ("delete:" + str (data ))
291- if self .root is None :
292- print ("Tree is empty!" )
293- return
294- self .root = del_node (self .root , data )
295-
296- def __str__ (
297- self ,
298- ) -> str : # a level traversale, gives a more intuitive look on the tree
299- output = ""
300- q = MyQueue ()
301- q .push (self .root )
302- layer = self .get_height ()
303- if layer == 0 :
304- return output
305- cnt = 0
306- while not q .is_empty ():
307- node = q .pop ()
308- space = " " * int (math .pow (2 , layer - 1 ))
309- output += space
310- if node is None :
311- output += "*"
312- q .push (None )
313- q .push (None )
314- else :
315- output += str (node .get_data ())
316- q .push (node .get_left ())
317- q .push (node .get_right ())
318- output += space
319- cnt = cnt + 1
320- for i in range (100 ):
321- if cnt == math .pow (2 , i ) - 1 :
322- layer = layer - 1
323- if layer == 0 :
324- output += "\n *************************************"
325- return output
326- output += "\n "
327- break
328- output += "\n *************************************"
329- return output
330-
331-
332- def _test () -> None :
333- import doctest
334-
335- doctest .testmod ()
336-
337-
338- if __name__ == "__main__" :
339- _test ()
340- t = AVLtree ()
341- lst = list (range (10 ))
342- random .shuffle (lst )
343- for i in lst :
344- t .insert (i )
345- print (str (t ))
346- random .shuffle (lst )
347- for i in lst :
348- t .del_node (i )
349- print (str (t ))
137+ # ✅ NEW FEATURE (YOUR CONTRIBUTION)
138+
139+ def inorder_traversal (root , result ):
140+ """
141+ Performs inorder traversal of AVL tree and stores result.
142+ """
143+ if root :
144+ inorder_traversal (root .get_left (), result )
145+ result .append (root .get_data ())
146+ inorder_traversal (root .get_right (), result )
147+
148+
149+ def avl_sort (arr ):
150+ """
151+ Sorts a list using AVL Tree.
152+
153+ Example:
154+ >>> avl_sort([3,1,2])
155+ [1, 2, 3]
156+ """
157+ tree = AVLtree ()
158+
159+ for value in arr :
160+ tree .insert (value )
161+
162+ result = []
163+ inorder_traversal (tree .root , result )
164+
165+ return result
0 commit comments