You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

b_tree.py 4.1KB

5 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. from SoSe24.algodat.foundation import AlgoDatArray, AlgoDatValue, read_int_sequence
  2. from time import perf_counter as pfc
  3. class BTreeNode:
  4. def __init__(self, m: int):
  5. self.n = 0
  6. self.leaf = True
  7. self.keys = AlgoDatArray(2 * m - 1)
  8. self.children = [None] * (2 * m)
  9. def __str__(self):
  10. return "(" + " ".join([str(self.keys[i]) for i in range(self.n)]) + ")"
  11. class BTree:
  12. def __init__(self, m: int):
  13. self.m = m
  14. self.root = BTreeNode(m)
  15. def search(self, key: AlgoDatValue, start: BTreeNode = None) -> BTreeNode:
  16. if not start:
  17. start = self.root
  18. i = 0
  19. while i < start.n and key > start.keys[i]:
  20. i += 1
  21. if i < start.n and key == start.keys[i]:
  22. return start
  23. if start.leaf:
  24. return None
  25. return self.search(key, start.children[i])
  26. def split_child(self, parent: BTreeNode, i: int):
  27. child = parent.children[i]
  28. h = BTreeNode(self.m)
  29. h.leaf = child.leaf
  30. h.n = self.m - 1
  31. for j in range(self.m - 1):
  32. h.keys[j] = child.keys[j + self.m]
  33. if not h.leaf:
  34. for j in range(self.m):
  35. h.children[j] = child.children[j + self.m]
  36. for j in range(self.m, child.n + 1):
  37. child.children[j] = None
  38. child.n = self.m - 1
  39. for j in range(parent.n, i, -1):
  40. parent.children[j + 1] = parent.children[j]
  41. parent.keys[j] = parent.keys[j - 1]
  42. parent.children[i + 1] = h
  43. parent.keys[i] = child.keys[self.m - 1]
  44. parent.n += 1
  45. def insert(self, k: AlgoDatValue):
  46. r = self.root
  47. if r.n == 2 * self.m - 1:
  48. h = BTreeNode(self.m)
  49. self.root = h
  50. h.leaf = False
  51. h.n = 0
  52. h.children[0] = r
  53. self.split_child(h, 0)
  54. self.insert_in_node(h, k)
  55. else:
  56. self.insert_in_node(r, k)
  57. def insert_in_node(self, start: BTreeNode, k: AlgoDatValue):
  58. i = start.n
  59. if start.leaf:
  60. while i >= 1 and k < start.keys[i-1]:
  61. start.keys[i] = start.keys[i-1]
  62. i -= 1
  63. start.keys[i] = k
  64. start.n += 1
  65. else:
  66. j = 0
  67. while j < start.n and k > start.keys[j]:
  68. j += 1
  69. if start.children[j].n == 2 * self.m - 1:
  70. self.split_child(start, j)
  71. if k > start.keys[j]:
  72. j += 1
  73. self.insert_in_node(start.children[j], k)
  74. def walk(self, start: BTreeNode = None):
  75. if not start:
  76. start = self.root
  77. i = 0
  78. while i < start.n:
  79. if not start.leaf:
  80. self.walk(start.children[i])
  81. print(start.keys[i], end=" ")
  82. i += 1
  83. if not start.leaf:
  84. self.walk(start.children[i])
  85. def height(self, start: BTreeNode = None):
  86. if not start:
  87. start = self.root
  88. if start.leaf:
  89. return 0
  90. return 1 + self.height(start.children[0])
  91. def graph_walk(self):
  92. queue = [ self.root ]
  93. with open("../../btree.gv", "w") as file:
  94. file.write("digraph BTree {\n")
  95. file.write(" node [fontname=\"Arial\"];\n")
  96. while queue:
  97. current = queue.pop(0)
  98. p = str(current)
  99. file.write(f'"{p}"; \n')
  100. i = 0
  101. while i <= current.n:
  102. if not current.leaf:
  103. queue.append(current.children[i])
  104. c = str(current.children[i])
  105. file.write(f'"{p}" -> "{c}";\n')
  106. i += 1
  107. file.write("}")
  108. if __name__ == "__main__":
  109. z = read_int_sequence("../../seq2.txt")
  110. start = pfc()
  111. tree = BTree(3)
  112. for i in z:
  113. tree.insert(i)
  114. print(f"Height: {tree.height()}")
  115. tree.walk()
  116. tree.graph_walk()
  117. s = tree.search(AlgoDatValue(0))
  118. print(f"\nKnoten mit 0: {str(s)}")
  119. print(f"Dauer: {pfc() - start:.4f}s")
  120. AlgoDatValue.summary()