diff --git a/vorlesung/L06_b_baeume/b_tree.py b/vorlesung/L06_b_baeume/b_tree.py new file mode 100644 index 0000000..7729930 --- /dev/null +++ b/vorlesung/L06_b_baeume/b_tree.py @@ -0,0 +1,120 @@ +from utils.literal import Literal +from utils.memory_cell import MemoryCell +from utils.memory_array import MemoryArray +from b_tree_node import BTreeNode + +class BTree: + def __init__(self, m: int): + self.m = m + self.root = BTreeNode(m) + + def search(self, value, start: BTreeNode = None) -> BTreeNode | None: + if not start: + start = self.root + start.load() + i = 0 + if not isinstance(value, MemoryCell): + value = MemoryCell(value) + while i < start.n and value > start.value[Literal(i)]: + i += 1 + if i < start.n and value == start.value[Literal(i)]: + return start + if start.leaf: + return None + return self.search(value, start.children[i]) + + def split_child(self, parent: BTreeNode, i: int): + child = parent.children[i] + child.load() + h = BTreeNode(self.m) + h.leaf = child.leaf + h.n = self.m - 1 + for j in range(self.m - 1): + h.value[Literal(j)] = child.value[Literal(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 + child.save() + h.save() + for j in range(parent.n, i, -1): + parent.children[j + 1] = parent.children[j] + parent.value[Literal(j)] = parent.value[Literal(j - 1)] + parent.children[i + 1] = h + parent.value[Literal(i)] = child.value[Literal(self.m - 1)] + parent.n += 1 + parent.save() + + def insert(self, value): + if not isinstance(value, MemoryCell): + value = MemoryCell(value) + 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, value) + else: + self.insert_in_node(r, value) + + def insert_in_node(self, start: BTreeNode, value): + start.load() + i = start.n + if start.leaf: + while i >= 1 and value < start.value[Literal(i-1)]: + start.value[Literal(i)] = start.value[Literal(i-1)] + i -= 1 + start.value[Literal(i)].set(value) + start.n += 1 + start.save() + else: + j = 0 + while j < start.n and value > start.value[Literal(j)]: + j += 1 + if start.children[j].n == 2 * self.m - 1: + self.split_child(start, j) + if value > start.value[Literal(j)]: + j += 1 + self.insert_in_node(start.children[j], value) + + def traversal(self, callback): + def traversal_recursive(node, callback): + i = 0 + while i < node.n: + if not node.leaf: + traversal_recursive(node.children[i], callback) + callback(node.value[Literal(i)]) + i += 1 + if not node.leaf: + traversal_recursive(node.children[i], callback) + + traversal_recursive(self.root, callback) + + def walk(self): + def print_key(key): + print(key, end=" ") + + self.traversal(print_key) + + def height(self, start: BTreeNode = None): + if not start: + start = self.root + if start.leaf: + return 0 + return 1 + self.height(start.children[0]) + + +if __name__ == "__main__": + a = MemoryArray.create_array_from_file("data/seq3.txt") + tree = BTree(3) + for cell in a: + tree.insert(cell) + print(f"Height: {tree.height()}") + tree.walk() + s = tree.search(0) + print(f"\nKnoten mit 0: {str(s)}") diff --git a/vorlesung/L06_b_baeume/b_tree_node.py b/vorlesung/L06_b_baeume/b_tree_node.py new file mode 100644 index 0000000..20b8bb5 --- /dev/null +++ b/vorlesung/L06_b_baeume/b_tree_node.py @@ -0,0 +1,29 @@ +from utils.literal import Literal +from utils.memory_cell import MemoryCell +from utils.memory_array import MemoryArray + +class BTreeNode(MemoryCell): + + def __init__(self, m: int): + super().__init__() + self.m = m + self.n = 0 + self.leaf = True + self.value = MemoryArray(Literal(2 * m - 1)) + self.children = [None] * (2 * m) + self.loaded_count = 0 + self.saved_count = 0 + + def reset_counters(self): + super().reset_counters() + self.loaded_count = 0 + self.saved_count = 0 + + def load(self): + self.loaded_count += 1 + + def save(self): + self.saved_count += 1 + + def __str__(self): + return "(" + " ".join([str(self.value[Literal(i)]) for i in range(self.n)]) + ")" \ No newline at end of file