-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPath_BST.py
150 lines (124 loc) · 4.22 KB
/
Path_BST.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
class Node:
def __init__(self, key, left=None, right=None):
self.key = key
self.left = left
self.right = right
class Tree:
def __init__(self, root=None):
self.root = root
# Search
def search(self, key):
return self._search_recursive(self.root, key)
def _search_recursive(self, node, key):
if node is None or node.key == key:
return node
elif key < node.key:
return self._search_recursive(node.left, key)
else:
return self._search_recursive(node.right, key)
# Insert
def insert(self, key):
new_root = self._insert_recursive(self.root, key)
return Tree(new_root)
def _insert_recursive(self, node, key):
if node is None:
return Node(key)
if key < node.key:
new_left = self._insert_recursive(node.left, key)
return Node(node.key, new_left, node.right)
elif key > node.key:
new_right = self._insert_recursive(node.right, key)
return Node(node.key, node.left, new_right)
else:
return node # Key already exists, no need to modify
# Delete
def delete(self, key):
new_root = self._delete_recursive(self.root, key)
return Tree(new_root)
def _delete_recursive(self, node, key):
if node is None:
return None
if key < node.key:
new_left = self._delete_recursive(node.left, key)
return Node(node.key, new_left, node.right)
elif key > node.key:
new_right = self._delete_recursive(node.right, key)
return Node(node.key, node.left, new_right)
else:
# Key found, delete it
if node.left is None:
return node.right
elif node.right is None:
return node.left
else:
# Node has two children
successor = self._find_min(node.right)
new_right = self._delete_recursive(node.right, successor.key)
return Node(successor.key, node.left, new_right)
def _find_min(self, node):
while node.left is not None:
node = node.left
return node
def view(self):
# Visualization of the tree structure using an iterative approach
if self.root is None:
print("Tree is empty")
return
# Stack to keep track of nodes and their depth
stack = [(self.root, 0)]
while stack:
node, depth = stack.pop()
# Print the current node with indentation based on its depth
print(" " * depth * 4 + f"-> {node.key}")
# Add children to the stack (right child first to print left child first)
if node.right is not None:
print("Right")
stack.append((node.right, depth + 1))
if node.left is not None:
print("Left")
stack.append((node.left, depth + 1))
#### INORDER TRAVERSAL
def printInorder(node):
if node is None:
return
# First recur on left subtree
printInorder(node.left)
# Now deal with the node
print(node.key, end=' ')
# Then recur on right subtree
printInorder(node.right)
#### Visualizing the tree
#Initialize an empty tree
tree = Tree()
# Perform insertions and keep track of tree versions
tree1 = tree.insert(5)
print("Tree Version 1:")
#tree1.view()
#printInorder(tree1.root)
print()
tree2 = tree1.insert(3)
print("Tree Version 2:")
#tree2.view()
printInorder(tree2.root)
print()
tree3 = tree2.insert(7)
print("Tree Version 3:")
printInorder(tree3.root)
#tree3.view()
print()
tree4 = tree3.insert(4)
print("Tree Version 4:")
printInorder(tree4.root)
#tree4.view()
print()
tree5 = tree4.insert(6)
print("Tree Version 5:")
printInorder(tree5.root)
#tree5.view()
print()
# Perform deletion and keep track of the new version
tree6 = tree5.delete(3)
print("Tree Version 6 (After deleting key 3):")
#tree6.view()
printInorder(tree6.root)
print()