123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- 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()
|