Repository navigation
Expand file tree
/
Copy pathAVLtree.py
More file actions
255 lines (255 loc) · 6.36 KB
/
Copy pathAVLtree.py
File metadata and controls
255 lines (255 loc) · 6.36 KB
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
import queue
class AVLNode:
def __init__(self,data):
self.data=data
self.right=None
self.left=None
self.parent=None
self.height=1
class AVLtree:
def __init__(self):
self.root=None
def visualize(self):
levels=self.printTree('levelorder')
h=self.root.height
n1=len(levels[-1])
n2=len(levels[-1])
for level in levels:
for node in level:
k=int(n2/len(level))
print(end=' '*(k-1))#beginning
print(node,end=' '*k)#end
n1=int(n1/2)
print('\r')
print('/'*n2*2,'(h->',h,')')
h-=1
def height(self,curnode):
if curnode:
return curnode.height
else:
return 0
def LeftRotate(self,z):
root=z.parent
y=z.right
t3=y.left
y.left=z
y.parent=root
z.parent=y
z.right=t3
if t3:
t3.parent=z
if not y.parent:
self.root=y
else:
if y.parent.left==z:
y.parent.left=y
else:
y.parent.right=y
z.height=max(self.height(z.left),self.height(z.right))+1
y.height=max(self.height(y.left),self.height(y.right))+1
def RightRotate(self,z):
root=z.parent
y=z.left
t3=y.right
y.right=z
y.parent=root
z.parent=y
z.left=t3
if t3:
t3.parent=z
if not y.parent:
self.root=y
else:
if y.parent.left==z:
y.parent.left=y
else:
y.parent.right=y
z.height=max(self.height(z.left),self.height(z.right))+1
y.height=max(self.height(y.left),self.height(y.right))+1
def insert(self,data):
if self.root is None:
self.root=AVLNode(data)
else:
self._insert(data,self.root)
def _insert(self,data,curnode):
if data<curnode.data:
if curnode.left is None:
curnode.left=AVLNode(data)
curnode.left.parent=curnode
self._inspectInsert(curnode.left)
else:
self._insert(data,curnode.left)
elif curnode.data<data:
if curnode.right is None:
curnode.right=AVLNode(data)
curnode.right.parent=curnode
self._inspectInsert(curnode.right)
else:
self._insert(data,curnode.right)
else:
print('duplicate instance of '+str(data)+' found')
curnode.height=max(self.height(curnode.left),self.height(curnode.right))+1
#print('tree after inserting ', data)
#print(self.__repr__())
def _inspectInsert(self,curnode,path=[]):
if not curnode.parent:
return
path=[curnode]+path
#for i in range(len(path)):
# print(path[i].data, end=' ')
#print()
lheight=self.height(curnode.parent.left)
rheight=self.height(curnode.parent.right)
if abs(lheight-rheight)>1:
path=[curnode.parent]+path
self._balanceAVL(path[0],path[1],path[2])
return
newheight=1+curnode.height
if newheight>curnode.parent.height:
curnode.parent.height=newheight
self._inspectInsert(curnode.parent,path)
def delete(self,data):
return self._delete(self.find(data))
def _delete(self,curnode):
def smallestnode(curnode):
while(curnode.left):
curnode=curnode.left
return curnode
def childrenNo(curnode):
count=0
if curnode.left:
count+=1
if curnode.right:
count+=1
return count
if not curnode:
print('value not present in tree')
return
else:
childcount=childrenNo(curnode)
parent=curnode.parent
if childcount==0:
if not parent:
self.root=None
else:
if curnode==parent.left:
parent.left=None
else:
parent.right=None
curnode.parent=None
if childcount==1:
if curnode.left:
curnode.data=curnode.left.data
curnode.left=None
else:
curnode.data=curnode.right.data
curnode.right=None
if childcount==2:
nextval=smallestnode(curnode.right)
curnode.data=nextval.data
self._delete(nextval)
return
if parent:
parent.height=max(self.height(parent.left),self.height(parent.right))
self._inspectDelete(parent)
def _inspectDelete(self,curnode):
if not curnode:
return
lheight=self.height(curnode.left)
rheight=self.height(curnode.right)
if abs(lheight-rheight)>1:
y=self._tallest(curnode)
x=self._tallest(y)
self._balanceAVL(curnode,y,x)
self._inspectDelete(curnode.parent)
def _tallest(self,curnode):
l=self.height(curnode.left)
r=self.height(curnode.right)
if l>=r:
return curnode.left
else:
return curnode.right
def _balanceAVL(self,z,y,x):
#left left
if y==z.left and x==y.left:
self.RightRotate(z)
# left right
elif y==z.left and x==y.right:
self.LeftRotate(y)
self.RightRotate(z)
#right right
elif y==z.right and x==y.right:
self.LeftRotate(z)
#right left
elif y==z.right and x==y.left:
self.RightRotate(y)
self.LeftRotate(z)
def find(self,data):
if self.root:
return self._find(self.root,data)
else:
return None
def _find(self,root,data):
if data==root.data:
return root
elif root.data>data and root.left:
return self._find(root.left,data)
elif root.data<data and root.right:
return self._find(root.right,data)
else:
return None
def printTree(self,print_type):
if print_type=='preorder':
return self.preorder_traverse(self.root)
elif print_type=='inorder':
return self.inorder_traverse(self.root)
elif print_type=='postorder':
return self.postorder_traverse(self.root)
elif print_type=='levelorder':
return self.levelorder_traverse(self.root)
def preorder_traverse(self,start,cache=[]):
if start:
cache.append(start.data)
self.preorder_traverse(start.left,cache)
self.preorder_traverse(start.right,cache)
return cache
def inorder_traverse(self,start,cache=[]):
if start:
self.inorder_traverse(start.left,cache)
cache.append(start.data)
self.inorder_traverse(start.right,cache)
return cache
def postorder_traverse(self,start,cache=[]):
if start:
self.postorder_traverse(start.left,cache)
self.postorder_traverse(start.right,cache)
cache.append(start.data)
return cache
def levelorder_traverse(self,start):
if start is None:
return
que=queue.Queue()
que.put(start)
level=AVLNode('level')
null=AVLNode(' ')
que.put(level)
cache=[]
result=[]
while(que.qsize()>0):
node=que.get()
if node==level:
que.put(level)
result.append(cache)
cache=[]
node=que.get()
cache.append(node.data)
if node!=null:
if node.left:
que.put(node.left)
else:
que.put(null)
if node.right:
que.put(node.right)
else:
que.put(null)
return result[:-1]