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.

bin_tree.py 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. from SoSe24.algodat.foundation import AlgoDatArray, AlgoDatValue, read_int_sequence
  2. from time import perf_counter as pfc
  3. class BinTreeNode:
  4. def __init__(self, value: AlgoDatValue):
  5. self.value = value
  6. self.left = None
  7. self.right = None
  8. def __str__(self):
  9. return f"{self.value}"
  10. def height(self) -> int:
  11. left_height = self.left.height() if self.left else 0
  12. right_height = self.right.height() if self.right else 0
  13. return 1 + max(left_height, right_height)
  14. class BinTree:
  15. def __init__(self):
  16. self.root = None
  17. def new_node(self, value: AlgoDatValue) -> BinTreeNode:
  18. return BinTreeNode(value)
  19. def insert(self, value: AlgoDatValue) -> (BinTreeNode, BinTreeNode):
  20. if not self.root:
  21. self.root = self.new_node(value)
  22. return self.root, None
  23. current = self.root
  24. while True:
  25. if value < current.value:
  26. if current.left:
  27. current = current.left
  28. else:
  29. current.left = self.new_node(value)
  30. return current.left, current
  31. elif value >= current.value:
  32. if current.right:
  33. current = current.right
  34. else:
  35. current.right = self.new_node(value)
  36. return current.right, current
  37. else:
  38. return None, None
  39. def search(self, value: AlgoDatValue) -> BinTreeNode:
  40. current = self.root
  41. while current:
  42. if value < current.value:
  43. current = current.left
  44. elif value > current.value:
  45. current = current.right
  46. else:
  47. return current
  48. return None
  49. def delete(self, value: AlgoDatValue):
  50. parent = None
  51. current = self.root
  52. while current:
  53. if value < current.value:
  54. parent = current
  55. current = current.left
  56. elif value >= current.value:
  57. parent = current
  58. current = current.right
  59. else:
  60. break
  61. else:
  62. return
  63. if current.left and current.right:
  64. parent = current
  65. successor = current.right
  66. while successor.left:
  67. parent = successor
  68. successor = successor.left
  69. current.value.value = successor.value.value
  70. current = successor
  71. if current.left:
  72. child = current.left
  73. else:
  74. child = current.right
  75. if not parent:
  76. self.root = child
  77. return child, None
  78. elif parent.left == current:
  79. parent.left = child
  80. return child, parent
  81. else:
  82. parent.right = child
  83. return child, parent
  84. def walk(self): # in-order
  85. print("[ ", end="")
  86. self.walk_recursive(self.root, 0, 0)
  87. print(" ]")
  88. def graph_walk(self):
  89. self.leaf_counter = 0
  90. with open("../../graph.gv", "w") as file:
  91. file.write("digraph BST {\n")
  92. file.write(" node [fontname=\"Arial\"];\n")
  93. self.graph_walk_recursive(self.root, file)
  94. file.write("}")
  95. def graph_walk_recursive(self, current, file):
  96. if current is not None:
  97. if current.left:
  98. file.write(f"{current.value} -> {current.left.value}; \n")
  99. self.graph_walk_recursive(current.left, file)
  100. else:
  101. file.write(f"left{self.leaf_counter} [shape=point]; \n")
  102. file.write(f"{current.value} -> left{self.leaf_counter}; \n")
  103. self.leaf_counter += 1
  104. if current.right:
  105. file.write(f"{current.value} -> {current.right.value}; \n")
  106. self.graph_walk_recursive(current.right, file)
  107. else:
  108. file.write(f"right{self.leaf_counter} [shape=point]; \n")
  109. file.write(f"{current.value} -> right{self.leaf_counter}; \n")
  110. self.leaf_counter += 1
  111. def tree_walk(self):
  112. self.walk_recursive(self.root, 0, 1)
  113. def walk_recursive(self, node: BinTreeNode, level = 0, increase = 1):
  114. if node:
  115. if increase >= 1:
  116. end = "\n"
  117. else:
  118. end = " "
  119. self.walk_recursive(node.left, level+increase, increase)
  120. print(" "*level*3 + str(node.value), end=end)
  121. self.walk_recursive(node.right, level+increase, increase)
  122. def levelwalk(self):
  123. if self.root is None:
  124. return
  125. queue = [self.root]
  126. while queue:
  127. current = queue.pop(0)
  128. print(current.value, end=" ")
  129. if current.left:
  130. queue.append(current.left)
  131. if current.right:
  132. queue.append(current.right)
  133. print()
  134. if __name__ == "__main__":
  135. z = read_int_sequence("../../seq0.txt")
  136. print(z, len(z))
  137. start = pfc()
  138. tree = BinTree()
  139. for i in z:
  140. tree.insert(i)
  141. tree.walk()
  142. tree.tree_walk()
  143. tree.levelwalk()
  144. tree.delete(AlgoDatValue(46))
  145. tree.graph_walk()
  146. print(f"Dauer: {pfc() - start:.4f}s")
  147. AlgoDatValue.summary()