from SoSe24.algodat.foundation import AlgoDatArray, AlgoDatValue, read_int_sequence from time import perf_counter as pfc class BTreeNode: def __init__(self, m: int): self.n = 0 self.leaf = True self.keys = AlgoDatArray(2 * m - 1) self.children = [None] * (2 * m) def __str__(self): return "(" + " ".join([str(self.keys[i]) for i in range(self.n)]) + ")" class BTree: def __init__(self, m: int): self.m = m self.root = BTreeNode(m) def search(self, key: AlgoDatValue, start: BTreeNode = None) -> BTreeNode: if not start: start = self.root i = 0 while i < start.n and key > start.keys[i]: i += 1 if i < start.n and key == start.keys[i]: return start if start.leaf: return None return self.search(key, start.children[i]) def split_child(self, parent: BTreeNode, i: int): child = parent.children[i] h = BTreeNode(self.m) h.leaf = child.leaf h.n = self.m - 1 for j in range(self.m - 1): h.keys[j] = child.keys[j + self.m] if not h.leaf: for j in range(self.m): h.children[j] = child.children[j + self.m] for j in range(self.m, child.n + 1): child.children[j] = None child.n = self.m - 1 for j in range(parent.n, i, -1): parent.children[j + 1] = parent.children[j] parent.keys[j] = parent.keys[j - 1] parent.children[i + 1] = h parent.keys[i] = child.keys[self.m - 1] parent.n += 1 def insert(self, k: AlgoDatValue): r = self.root if r.n == 2 * self.m - 1: h = BTreeNode(self.m) self.root = h h.leaf = False h.n = 0 h.children[0] = r self.split_child(h, 0) self.insert_in_node(h, k) else: self.insert_in_node(r, k) def insert_in_node(self, start: BTreeNode, k: AlgoDatValue): i = start.n if start.leaf: while i >= 1 and k < start.keys[i-1]: start.keys[i] = start.keys[i-1] i -= 1 start.keys[i] = k start.n += 1 else: j = 0 while j < start.n and k > start.keys[j]: j += 1 if start.children[j].n == 2 * self.m - 1: self.split_child(start, j) if k > start.keys[j]: j += 1 self.insert_in_node(start.children[j], k) def walk(self, start: BTreeNode = None): if not start: start = self.root i = 0 while i < start.n: if not start.leaf: self.walk(start.children[i]) print(start.keys[i], end=" ") i += 1 if not start.leaf: self.walk(start.children[i]) def height(self, start: BTreeNode = None): if not start: start = self.root if start.leaf: return 0 return 1 + self.height(start.children[0]) def graph_walk(self): queue = [ self.root ] with open("../../btree.gv", "w") as file: file.write("digraph BTree {\n") file.write(" node [fontname=\"Arial\"];\n") while queue: current = queue.pop(0) p = str(current) file.write(f'"{p}"; \n') i = 0 while i <= current.n: if not current.leaf: queue.append(current.children[i]) c = str(current.children[i]) file.write(f'"{p}" -> "{c}";\n') i += 1 file.write("}") if __name__ == "__main__": z = read_int_sequence("../../seq2.txt") start = pfc() tree = BTree(3) for i in z: tree.insert(i) print(f"Height: {tree.height()}") tree.walk() tree.graph_walk() s = tree.search(AlgoDatValue(0)) print(f"\nKnoten mit 0: {str(s)}") print(f"Dauer: {pfc() - start:.4f}s") AlgoDatValue.summary()