Got a task: to implement a dictionary based on a search tree with B-balancing, in which the data is stored in leaves.
I wrote a dictionary class: B-balanced segment tree. I understand that a search tree with keys k1, k2, k3 ... kn corresponds to a segment tree with segments, or rather, half-intervals (-inf,k1) [k1, k2) [k2, k3) ... [kn, inf) , but I don't understand how to implement it in terms of my class. I would really appreciate any help.
class Node:
def __init__(self, segment,value = None,children = []):
self.segment = segment
self.value = value
self.children = children
self.exist = 1
class Dict():
def __init__(self):
self.root = None
self.len = 0
self.t = 4
self.combine = sum
def __len__(self):
return self.len
def __getitem__(self, key):
if not self.root:
raise KeyError()
else:
return self.get(self.root, key)
def __contains__(self, key):
try:
self.__getitem__(key)
return True
except:
return False
def __setitem__(self, key, value):
if not self.root:
self.root = self.make_branch([self.make_leaf(key,value)])
self.len += 1
else:
if key not in self:
self.len += 1
self.root = self.tree_put(self.root, key, value)
def __delitem__(self, key):
if key not in self:
raise KeyError()
else:
self.delete(self.root, key)
self.len -= 1
def get(self,tree,key):
if key == tree.segment[0] and key == tree.segment[1] and tree.exist == 1:
return tree.value
elif tree.segment[0] != tree.segment[1]:
i = 0
while i < len(tree.children):
if tree.children[i].segment[0] > key: break
i+=1
try:
return self.get(tree.children[i-1],key)
except:
raise KeyError()
raise KeyError()
def delete(self, tree, key):
if key == tree.segment[0] and key == tree.segment[1] and tree.exist == 1:
tree.exist = 0
return
elif tree.segment[0] != tree.segment[1]:
i = 0
if len(tree.children) > 0:
while i < len(tree.children):
if tree.children[i].segment[0] >= key: break
i+=1
try:
return self.delete(tree.children[i],key)
except:
return self.delete(tree.children[i-1],key)
raise KeyError()
def make_leaf(self, key, value): return Node((key, key), self.combine([value]), [] )
def make_branch(self, trees):
segments = [ tree.segment for tree in trees ]
left = segments[0][0]
right = segments[-1][1]
value = self.combine([ tree.value for tree in trees ])
return Node((left, right), value, trees[:])
def tree_segment_value(self, tree, a, b):
ta, tb = tree.segment
if a <= ta and tb <= b: return tree.value
to_combine = []
for child in tree.children:
ta, tb = child.segment
if tb < a: continue
if ta > b: break
if a <= ta and tb <= b: to_combine.append(child.value)
else: to_combine.append(tree_segment_value(child, a, b))
return self.combine(to_combine)
def tree_put_rec(self,tree,key,value):
if tree == None:
return [self.make_branch([self.make_leaf(key,value)])]
i = 0
while i < len(tree.children):
if tree.children[i].segment[0] > key: break
i+=1
if i > 0: i-=1
left_children = tree.children[:i]
right_children = tree.children[i+1:]
child = tree.children[i]
if len(child.children) == 0:
new_leaf = self.make_leaf(key,value)
child_key = child.segment[0]
if child_key < key: mid_children = [child,new_leaf]
elif child_key > key: mid_children = [new_leaf,child]
else: mid_children = [new_leaf]
else:
mid_children = self.tree_put_rec(child,key,value)
new_children = left_children+mid_children+right_children
N = len(new_children)
if N > self.t: to_wrap = [new_children[:N//2],new_children[N//2:]]
else: to_wrap = [new_children]
return [self.make_branch(subtrees) for subtrees in to_wrap]
def tree_put(self, tree,key,value):
new_trees = self.tree_put_rec(tree,key,value)
if len(new_trees) < 2: return new_trees[0]
return self.make_branch(new_trees)