0

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)

0 Answers0