Skip to content

Commit 088fd4b

Browse files
Added AVL sort using inorder traversal and improved code quality
1 parent 68473af commit 088fd4b

File tree

1 file changed

+55
-239
lines changed

1 file changed

+55
-239
lines changed
Lines changed: 55 additions & 239 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
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-
91
from __future__ import annotations
102

113
import 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

4327
class 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

7556
def 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

8160
def 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

8764
def 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

11076
def 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

12688
def 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

14393
def 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

245126
class 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

Comments
 (0)