Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 069c043

Browse files
B-tree in Python
1 parent 215ba70 commit 069c043

File tree

1 file changed

+350
-0
lines changed

1 file changed

+350
-0
lines changed

‎Trees/B-tree.py

Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
# Copyright (C) Deepali Srivastava - All Rights Reserved
2+
# This code is part of DSA course available on CourseGalaxy.com
3+
4+
from math import ceil
5+
6+
class Node:
7+
def __init__(self,size):
8+
self.numKeys = 0
9+
self.key = [None] * size
10+
self.child = [None] * size
11+
12+
class BTree:
13+
M = 5
14+
MAX = M - 1
15+
MIN = ceil(M/2) - 1
16+
17+
18+
def __init__(self):
19+
self.root = None
20+
21+
def isEmpty(self):
22+
return self.root == None
23+
24+
def search(self, x):
25+
if self._search(x, self.root) == None:
26+
return False
27+
return True
28+
29+
def _search(self, x, p):
30+
if p == None : # Key x not present in the tree
31+
return None
32+
33+
flag, n = self._searchNode(x, p)
34+
if flag == True: # Key x found in node p
35+
return p
36+
37+
return self._search(x, p.child[n]) # Search in node p.child[n]
38+
39+
40+
def _searchNode(self, x, p):
41+
if x < p.key[1] : # key x is less than leftmost key
42+
return False,0
43+
44+
n = p.numKeys
45+
while (x < p.key[n]) and n > 1 :
46+
n -= 1
47+
48+
if x == p.key[n]:
49+
return True,n
50+
else:
51+
return False,n
52+
53+
54+
def inorder(self):
55+
self._inorder(self.root)
56+
print()
57+
58+
59+
def _inorder(self, p):
60+
if p == None:
61+
return
62+
63+
i = 0
64+
while i < p.numKeys:
65+
self._inorder(p.child[i])
66+
print(p.key[i+1] , end = " ")
67+
i += 1
68+
69+
self._inorder( p.child[i] )
70+
71+
72+
def display(self):
73+
self._display(self.root, 0)
74+
75+
76+
def _display(self, p, blanks):
77+
if p != None :
78+
for i in range(blanks):
79+
print(end = " ")
80+
81+
for i in range(1,p.numKeys+1):
82+
print(p.key[i] ,end=" ")
83+
print()
84+
85+
for i in range(p.numKeys+1):
86+
self._display(p.child[i], blanks + 10)
87+
88+
89+
def insert(self, x):
90+
91+
taller, iKey, iKeyRchild = self._insert(x, self.root)
92+
93+
if taller: # Height increased by one, new root node has to be created
94+
temp = Node(BTree.M)
95+
temp.child[0] = self.root
96+
self.root = temp
97+
98+
self.root.numKeys = 1
99+
self.root.key[1] = iKey
100+
self.root.child[1] = iKeyRchild
101+
102+
103+
def _insert(self, x, p):
104+
105+
if p == None: #First Base case : key not found
106+
return True, x, None
107+
108+
flag, n = self._searchNode(x, p)
109+
110+
if flag == True : #Second Base Case : key found
111+
print("Key already present in the tree")
112+
return False, 0 , None #No need to insert the key
113+
114+
115+
flag, iKey, iKeyRchild = self._insert(x, p.child[n])
116+
117+
if flag == True:
118+
if p.numKeys < BTree.MAX:
119+
self._insertByShift(p, n, iKey, iKeyRchild)
120+
return False,iKey, iKeyRchild #Insertion over
121+
else:
122+
iKey, iKeyRchild = self._split(p, n, iKey, iKeyRchild )
123+
return True,iKey, iKeyRchild #Insertion not over : Median key yet to be inserted
124+
return False, iKey, iKeyRchild
125+
126+
127+
def _insertByShift(self, p, n, iKey, iKeyRchild):
128+
i = p.numKeys
129+
while i > n:
130+
p.key[i+1] = p.key[i]
131+
p.child[i+1] = p.child[i]
132+
i -= 1
133+
134+
p.key[n+1] = iKey
135+
p.child[n+1] = iKeyRchild
136+
p.numKeys += 1
137+
138+
139+
def _split(self, p, n,iKey, iKeyRchild):
140+
if n == BTree.MAX:
141+
lastKey = iKey
142+
lastChild = iKeyRchild
143+
else:
144+
lastKey = p.key[BTree.MAX]
145+
lastChild = p.child[BTree.MAX]
146+
147+
i = p.numKeys-1
148+
while i>n :
149+
p.key[i + 1] = p.key[i]
150+
p.child[i + 1] = p.child[i]
151+
i -= 1
152+
153+
p.key[i+1] = iKey
154+
p.child[i+1] = iKeyRchild
155+
156+
157+
d = (BTree.M + 1) // 2
158+
medianKey = p.key[d]
159+
newNode = Node(BTree.M)
160+
newNode.numKeys = BTree.M - d
161+
162+
newNode.child[0] = p.child[d]
163+
i=1
164+
j=d+1
165+
166+
while j <= BTree.MAX :
167+
newNode.key[i] = p.key[j]
168+
newNode.child[i] = p.child[j]
169+
i += 1
170+
j += 1
171+
172+
newNode.key[i] = lastKey
173+
newNode.child[i] = lastChild
174+
175+
p.numKeys = d - 1
176+
177+
iKey = medianKey
178+
iKeyRchild = newNode
179+
180+
return iKey, iKeyRchild
181+
182+
183+
def delete(self, x):
184+
if self.root == None :
185+
print("Tree is empty")
186+
return
187+
188+
self._delete(x, self.root)
189+
190+
if self.root != None and self.root.numKeys == 0: #Height of tree decreased by 1
191+
self.root = self.root.child[0]
192+
193+
194+
def _delete(self, x, p):
195+
196+
flag, n = self._searchNode(x, p)
197+
198+
if flag == True: # Key x found in node p
199+
if p.child[n] == None: # Node p is a leaf node
200+
self._deleteByShift(p, n)
201+
return
202+
else: # Node p is a non-leaf node
203+
s = p.child[n]
204+
while s.child[0] != None:
205+
s = s.child[0]
206+
p.key[n] = s.key[1]
207+
self._delete(s.key[1], p.child[n])
208+
else: # Key x not found in node p
209+
if p.child[n] == None : # p is a leaf node
210+
print("Value", x , " not present in the tree")
211+
return
212+
else: # p is a non-leaf node
213+
self._delete(x, p.child[n])
214+
215+
if p.child[n].numKeys < BTree.MIN :
216+
self._restore(p,n)
217+
218+
219+
def _deleteByShift(self, p, n):
220+
for i in range(n+1,p.numKeys+1):
221+
p.key[i-1] = p.key[i]
222+
p.child[i-1] = p.child[i]
223+
p.numKeys -= 1
224+
225+
226+
# Called when p.child[n] becomes underflow
227+
def _restore(self, p, n):
228+
if n!=0 and p.child[n-1].numKeys > BTree.MIN :
229+
self._borrowLeft(p, n)
230+
elif n!=p.numKeys and p.child[n+1].numKeys > BTree.MIN:
231+
self._borrowRight(p, n)
232+
else:
233+
if n!=0 : #if there is a left sibling
234+
self._combine(p, n) # combine with left sibling
235+
else:
236+
self._combine(p, n+1) # combine with right sibling
237+
238+
239+
def _borrowLeft(self, p, n):
240+
underflowNode = p.child[n]
241+
leftSibling = p.child[n - 1]
242+
243+
underflowNode.numKeys += 1
244+
245+
#Shift all the keys and children in underflowNode one position right
246+
for i in range(underflowNode.numKeys, 0, -1):
247+
underflowNode.key[i+1] = underflowNode.key[i]
248+
underflowNode.child[i+1] = underflowNode.child[i]
249+
250+
underflowNode.child[1] = underflowNode.child[0]
251+
252+
# Move the separator key from parent node p to underflowNode
253+
underflowNode.key[1] = p.key[n]
254+
255+
# Move the rightmost key of node leftSibling to the parent node p
256+
p.key[n] = leftSibling.key[leftSibling.numKeys]
257+
258+
#Rightmost child of leftSibling becomes leftmost child of underflowNode
259+
underflowNode.child[0] = leftSibling.child[leftSibling.numKeys]
260+
261+
leftSibling.numKeys -= 1
262+
263+
264+
def _borrowRight(self, p, n):
265+
underflowNode = p.child[n]
266+
rightSibling = p.child[n+1]
267+
268+
# Move the separator key from parent node p to underflowNode
269+
underflowNode.numKeys += 1
270+
underflowNode.key[underflowNode.numKeys] = p.key[n+1]
271+
272+
# Leftmost child of rightSibling becomes the rightmost child of underflowNode
273+
underflowNode.child[underflowNode.numKeys] = rightSibling.child[0]
274+
275+
rightSibling.numKeys -= 1
276+
277+
# Move the leftmost key from rightSibling to parent node p
278+
p.key[n+1] = rightSibling.key[1]
279+
280+
# Shift all the keys and children of rightSibling one position left
281+
rightSibling.child[0] = rightSibling.child[1]
282+
for i in range(1,rightSibling.numKeys+1):
283+
rightSibling.key[i] = rightSibling.key[i + 1]
284+
rightSibling.child[i] = rightSibling.child[i + 1]
285+
286+
287+
def _combine(self, p, m):
288+
nodeA = p.child[m-1]
289+
nodeB = p.child[m]
290+
291+
nodeA.numKeys += 1
292+
293+
# Move the separator key from the parent node p to nodeA
294+
nodeA.key[nodeA.numKeys] = p.key[m]
295+
296+
# Shift the keys and children that are after separator key in node p one position left
297+
for i in range(m, p.numKeys):
298+
p.key[i] = p.key[i+1]
299+
p.child[i] = p.child[i+1]
300+
301+
p.numKeys -= 1
302+
303+
# Leftmost child of nodeB becomes rightmost child of nodeA
304+
nodeA.child[nodeA.numKeys] = nodeB.child[0]
305+
306+
# Insert all the keys and children of nodeB at the end of nodeA
307+
for i in range(1, nodeB.numKeys+1):
308+
nodeA.numKeys += 1
309+
nodeA.key[nodeA.numKeys] = nodeB.key[i]
310+
nodeA.child[nodeA.numKeys] = nodeB.child[i]
311+
312+
313+
##############################################################################################
314+
315+
if __name__ == '__main__':
316+
317+
tree = BTree()
318+
319+
while True:
320+
321+
print("1.Search")
322+
print("2.Insert")
323+
print("3.Delete")
324+
print("4.Display")
325+
print("5.Inorder Traversal")
326+
print("6.Quit")
327+
choice = int(input("Enter your choice : "))
328+
329+
if choice == 1:
330+
key = int(input("Enter the key to be searched : "))
331+
if tree.search(key) == True:
332+
print("Key found")
333+
else:
334+
print("Key not found")
335+
elif choice == 2:
336+
key = int(input("Enter the key to be inserted : "))
337+
tree.insert(key)
338+
elif choice == 3:
339+
key = int(input("Enter the element to be deleted : "))
340+
tree.delete(key)
341+
elif choice == 4:
342+
tree.display()
343+
elif choice == 5:
344+
tree.inorder()
345+
elif choice == 6:
346+
break
347+
else:
348+
print("Wrong choice")
349+
print()
350+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /