forked from hofmannol/AlgoDatSoSe25
Compare commits
No commits in common. "e848e3089e556f0cc95f72a2c62ede7071e54eed" and "1a2f826a06b7b13945a5e6ca51d912aa05bf45fc" have entirely different histories.
e848e3089e
...
1a2f826a06
@ -1,12 +0,0 @@
|
|||||||
from utils.memory_array import MemoryArray
|
|
||||||
from vorlesung.L05_binaere_baeume.avl_tree import AVLTree
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
a = MemoryArray.create_array_from_file("data/seq0.txt")
|
|
||||||
tree = AVLTree()
|
|
||||||
|
|
||||||
for cell in a:
|
|
||||||
tree.insert(int(cell))
|
|
||||||
|
|
||||||
tree.graph_traversal()
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
from utils.memory_array import MemoryArray
|
|
||||||
from vorlesung.L05_binaere_baeume.bin_tree import BinaryTree
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
a = MemoryArray.create_array_from_file("data/seq0.txt")
|
|
||||||
tree = BinaryTree()
|
|
||||||
|
|
||||||
for cell in a:
|
|
||||||
tree.insert(int(cell))
|
|
||||||
|
|
||||||
tree.graph_traversal()
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
|||||||
matplotlib
|
matplotlib
|
||||||
numpy
|
numpy
|
||||||
pygame
|
pygame
|
||||||
graphviz
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
from utils.memory_manager import MemoryManager
|
|
||||||
from utils.memory_array import MemoryArray
|
|
||||||
from utils.literal import Literal
|
|
||||||
from vorlesung.L05_binaere_baeume.avl_tree import AVLTree
|
|
||||||
|
|
||||||
def analyze_complexity(sizes):
|
|
||||||
"""
|
|
||||||
Analysiert die Komplexität
|
|
||||||
|
|
||||||
:param sizes: Eine Liste von Eingabegrößen für die Analyse.
|
|
||||||
"""
|
|
||||||
for size in sizes:
|
|
||||||
MemoryManager.purge() # Speicher zurücksetzen
|
|
||||||
tree = AVLTree()
|
|
||||||
random_array = MemoryArray.create_random_array(size, -100, 100)
|
|
||||||
for i in range(size-1):
|
|
||||||
tree.insert(int(random_array[Literal(i)]))
|
|
||||||
MemoryManager.reset()
|
|
||||||
tree.insert(int(random_array[Literal(size-1)]))
|
|
||||||
MemoryManager.save_stats(size)
|
|
||||||
|
|
||||||
MemoryManager.plot_stats(["cells", "compares"])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sizes = range(1, 1001, 2)
|
|
||||||
analyze_complexity(sizes)
|
|
@ -1,94 +0,0 @@
|
|||||||
from utils.memory_array import MemoryArray
|
|
||||||
from vorlesung.L05_binaere_baeume.avl_tree_node import AVLTreeNode
|
|
||||||
from vorlesung.L05_binaere_baeume.bin_tree import BinaryTree
|
|
||||||
import logging
|
|
||||||
|
|
||||||
class AVLTree(BinaryTree):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
def new_node(self, value):
|
|
||||||
return AVLTreeNode(value)
|
|
||||||
|
|
||||||
|
|
||||||
def balance(self, node: AVLTreeNode):
|
|
||||||
node.update_balance()
|
|
||||||
if node.balance == -2:
|
|
||||||
if node.left.balance <= 0:
|
|
||||||
node = node.right_rotate()
|
|
||||||
else:
|
|
||||||
node = node.left_right_rotate()
|
|
||||||
elif node.balance == 2:
|
|
||||||
if node.right.balance >= 0:
|
|
||||||
node = node.left_rotate()
|
|
||||||
else:
|
|
||||||
node = node.right_left_rotate()
|
|
||||||
if node.parent:
|
|
||||||
self.balance(node.parent)
|
|
||||||
else:
|
|
||||||
self.root = node
|
|
||||||
|
|
||||||
def insert(self, value):
|
|
||||||
insert_generator = self.insert_stepwise(value)
|
|
||||||
node, parent = None, None
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
node, parent = next(insert_generator)
|
|
||||||
except StopIteration:
|
|
||||||
break
|
|
||||||
return node, parent
|
|
||||||
|
|
||||||
def insert_stepwise(self, value):
|
|
||||||
node, parent = super().insert(value)
|
|
||||||
yield None, None
|
|
||||||
node.parent = parent
|
|
||||||
if parent:
|
|
||||||
self.balance(parent)
|
|
||||||
return node, parent
|
|
||||||
|
|
||||||
|
|
||||||
def delete(self, value):
|
|
||||||
node, parent = super().delete(value)
|
|
||||||
if node:
|
|
||||||
node.parent = parent
|
|
||||||
if parent:
|
|
||||||
self.balance(parent)
|
|
||||||
|
|
||||||
def graph_filename(self):
|
|
||||||
return "AVLTree"
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
|
|
||||||
def print_node(node, indent=0, level=0):
|
|
||||||
print((indent * 3) * " ", node.value)
|
|
||||||
|
|
||||||
tree = AVLTree()
|
|
||||||
#values = [5, 3, 7, 2, 4, 6, 5, 8]
|
|
||||||
values = MemoryArray.create_array_from_file("data/seq2.txt")
|
|
||||||
|
|
||||||
for value in values:
|
|
||||||
tree.insert(value)
|
|
||||||
|
|
||||||
|
|
||||||
print("In-order traversal:")
|
|
||||||
tree.in_order_traversal(print_node)
|
|
||||||
print("\nLevel-order traversal:")
|
|
||||||
tree.level_order_traversal(print_node)
|
|
||||||
print("\nTree structure traversal:")
|
|
||||||
tree.tree_structure_traversal(print_node)
|
|
||||||
print("\nGraph traversal:")
|
|
||||||
tree.graph_traversal()
|
|
||||||
|
|
||||||
tree.insert(9)
|
|
||||||
tree.graph_traversal()
|
|
||||||
|
|
||||||
print("\nDeleting 5:")
|
|
||||||
tree.delete(5)
|
|
||||||
|
|
||||||
print("In-order traversal after deletion:")
|
|
||||||
tree.in_order_traversal(print_node)
|
|
||||||
print("\nLevel-order traversal after deletion:")
|
|
||||||
tree.level_order_traversal(print_node)
|
|
||||||
print("\nTree structure traversal after deletion:")
|
|
||||||
tree.tree_structure_traversal(print_node)
|
|
@ -1,59 +0,0 @@
|
|||||||
import random
|
|
||||||
import pygame
|
|
||||||
from utils.game import Game
|
|
||||||
from avl_tree import AVLTree
|
|
||||||
|
|
||||||
WHITE = (255, 255, 255)
|
|
||||||
BLUE = (0, 0, 255)
|
|
||||||
BLACK = (0, 0, 0)
|
|
||||||
WIDTH = 800
|
|
||||||
HEIGHT = 400
|
|
||||||
MARGIN = 20
|
|
||||||
|
|
||||||
class AVLTreeGame(Game):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__("AVLTree Game", fps=10, size=(WIDTH, HEIGHT))
|
|
||||||
random.seed()
|
|
||||||
self.z = list(range(1, 501))
|
|
||||||
random.shuffle(self.z)
|
|
||||||
self.finished = False
|
|
||||||
self.tree = AVLTree()
|
|
||||||
self.tree.get_height = lambda node: 0 if node is None else 1 + max(self.tree.get_height(node.left), self.tree.get_height(node.right))
|
|
||||||
self.height = self.tree.get_height(self.tree.root)
|
|
||||||
self.generator = None
|
|
||||||
|
|
||||||
def update_game(self):
|
|
||||||
if not self.finished:
|
|
||||||
if self.generator is None:
|
|
||||||
self.generator = self.tree.insert_stepwise(self.z.pop())
|
|
||||||
try:
|
|
||||||
next(self.generator)
|
|
||||||
except StopIteration:
|
|
||||||
self.generator = None
|
|
||||||
if self.generator is None and len(self.z) == 0:
|
|
||||||
self.finished = True
|
|
||||||
self.height = self.tree.get_height(self.tree.root)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def draw_game(self):
|
|
||||||
self.screen.fill(WHITE)
|
|
||||||
if self.height > 0:
|
|
||||||
self.draw_tree(self.tree.root, WIDTH // 2, MARGIN, WIDTH // 4 - MARGIN)
|
|
||||||
super().draw_game()
|
|
||||||
|
|
||||||
def draw_tree(self, node, x, y, x_offset):
|
|
||||||
y_offset = (HEIGHT - (2 * MARGIN)) / self.height
|
|
||||||
if node is not None:
|
|
||||||
pygame.draw.circle(self.screen, BLUE, (x, y), 2)
|
|
||||||
if node.left is not None:
|
|
||||||
pygame.draw.line(self.screen, BLACK, (x, y), (x - x_offset, y + y_offset))
|
|
||||||
self.draw_tree(node.left, x - x_offset, y + y_offset, x_offset // 2)
|
|
||||||
if node.right is not None:
|
|
||||||
pygame.draw.line(self.screen, BLACK, (x, y), (x + x_offset, y + y_offset))
|
|
||||||
self.draw_tree(node.right, x + x_offset, y + y_offset, x_offset // 2)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
tree_game = AVLTreeGame()
|
|
||||||
tree_game.run()
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
|||||||
from vorlesung.L05_binaere_baeume.bin_tree_node import BinaryTreeNode
|
|
||||||
|
|
||||||
class AVLTreeNode(BinaryTreeNode):
|
|
||||||
def __init__(self, value):
|
|
||||||
super().__init__(value)
|
|
||||||
self.parent = None
|
|
||||||
self.balance = 0
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"TreeNode(id={id(self)} value={self.value}, left={self.left}, right={self.right})"
|
|
||||||
|
|
||||||
def graphviz_rep(self, row, col, dot):
|
|
||||||
dot.node(str(id(self)), label=str(self.value), pos=f"{col},{-row}!", xlabel=str(self.balance))
|
|
||||||
|
|
||||||
def update_balance(self):
|
|
||||||
left_height = self.left.height() if self.left else 0
|
|
||||||
right_height = self.right.height() if self.right else 0
|
|
||||||
self.balance = right_height - left_height
|
|
||||||
|
|
||||||
def right_rotate(self):
|
|
||||||
new_root = self.left
|
|
||||||
new_root.parent = self.parent
|
|
||||||
self.left = new_root.right
|
|
||||||
if self.left:
|
|
||||||
self.left.parent = self
|
|
||||||
new_root.right = self
|
|
||||||
self.parent = new_root
|
|
||||||
if new_root.parent:
|
|
||||||
if new_root.parent.left is self:
|
|
||||||
new_root.parent.left = new_root
|
|
||||||
else:
|
|
||||||
new_root.parent.right = new_root
|
|
||||||
self.update_balance()
|
|
||||||
new_root.update_balance()
|
|
||||||
return new_root
|
|
||||||
|
|
||||||
def left_rotate(self):
|
|
||||||
new_root = self.right
|
|
||||||
new_root.parent = self.parent
|
|
||||||
self.right = new_root.left
|
|
||||||
if self.right:
|
|
||||||
self.right.parent = self
|
|
||||||
new_root.left = self
|
|
||||||
self.parent = new_root
|
|
||||||
if new_root.parent:
|
|
||||||
if new_root.parent.left is self:
|
|
||||||
new_root.parent.left = new_root
|
|
||||||
else:
|
|
||||||
new_root.parent.right = new_root
|
|
||||||
self.update_balance()
|
|
||||||
new_root.update_balance()
|
|
||||||
return new_root
|
|
||||||
|
|
||||||
def right_left_rotate(self):
|
|
||||||
self.right = self.right.right_rotate()
|
|
||||||
return self.left_rotate()
|
|
||||||
|
|
||||||
def left_right_rotate(self):
|
|
||||||
self.left = self.left.left_rotate()
|
|
||||||
return self.right_rotate()
|
|
||||||
|
|
@ -3,7 +3,6 @@ from utils.memory_manager import MemoryManager
|
|||||||
from utils.memory_array import MemoryArray
|
from utils.memory_array import MemoryArray
|
||||||
from utils.project_dir import get_path
|
from utils.project_dir import get_path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import graphviz
|
|
||||||
|
|
||||||
|
|
||||||
class BinaryTree:
|
class BinaryTree:
|
||||||
@ -70,7 +69,7 @@ class BinaryTree:
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# Wert nicht gefunden
|
# Wert nicht gefunden
|
||||||
return None, None
|
return
|
||||||
return self.delete_node(current, parent)
|
return self.delete_node(current, parent)
|
||||||
|
|
||||||
def delete_node(self, current, parent):
|
def delete_node(self, current, parent):
|
||||||
@ -145,35 +144,37 @@ class BinaryTree:
|
|||||||
line = 0
|
line = 0
|
||||||
tree_structure_traversal_recursive(callback, self.root, 0)
|
tree_structure_traversal_recursive(callback, self.root, 0)
|
||||||
|
|
||||||
def graph_filename(self):
|
|
||||||
return "BinaryTree"
|
|
||||||
|
|
||||||
def graph_traversal(self):
|
def graph_traversal(self):
|
||||||
|
|
||||||
def define_node(node, level, line):
|
def define_node(node, level, line):
|
||||||
nonlocal dot
|
nonlocal file
|
||||||
if node is not None:
|
if node is not None:
|
||||||
node.graphviz_rep(level, line, dot)
|
file.write(node.gv_rep(level, line))
|
||||||
|
|
||||||
def graph_traversal_recursive(current):
|
def graph_traversal_recursive(current):
|
||||||
nonlocal dot
|
nonlocal file
|
||||||
if current is not None:
|
if current is not None:
|
||||||
if current.left:
|
if current.left:
|
||||||
dot.edge(str(id(current)), str(id(current.left)))
|
file.write(f"{id(current)} -> {id(current.left)}; \n")
|
||||||
graph_traversal_recursive(current.left)
|
graph_traversal_recursive(current.left)
|
||||||
if current.right:
|
if current.right:
|
||||||
dot.edge(str(id(current)), str(id(current.right)))
|
file.write(f"{id(current)} -> {id(current.right)}; \n")
|
||||||
graph_traversal_recursive(current.right)
|
graph_traversal_recursive(current.right)
|
||||||
|
|
||||||
dot = graphviz.Digraph( name="BinaryTree",
|
timestamp = datetime.now().strftime("%Y%m%d_%H:%M:%S")
|
||||||
engine="neato",
|
filename = f"graph_{timestamp}.gv"
|
||||||
node_attr={"shape": "circle", "fontname": "Arial"},
|
filename = get_path(filename)
|
||||||
format="pdf" )
|
with open(filename, "w") as file:
|
||||||
|
file.write("digraph BST {\n")
|
||||||
|
file.write("layout=neato;\n")
|
||||||
|
file.write("node [shape=circle, fontname=\"Arial\"];\n")
|
||||||
self.tree_structure_traversal(define_node)
|
self.tree_structure_traversal(define_node)
|
||||||
graph_traversal_recursive(self.root)
|
graph_traversal_recursive(self.root)
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
file.write("}")
|
||||||
filename = f"{self.graph_filename()}_{timestamp}.gv"
|
|
||||||
filename = get_path(filename)
|
|
||||||
dot.render(filename)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
tree = BinaryTree()
|
tree = BinaryTree()
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
import random
|
|
||||||
import pygame
|
|
||||||
from utils.game import Game
|
|
||||||
from bin_tree import BinaryTree
|
|
||||||
|
|
||||||
WHITE = (255, 255, 255)
|
|
||||||
BLUE = (0, 0, 255)
|
|
||||||
BLACK = (0, 0, 0)
|
|
||||||
WIDTH = 800
|
|
||||||
HEIGHT = 400
|
|
||||||
MARGIN = 20
|
|
||||||
|
|
||||||
class BinTreeGame(Game):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__("BinTree Game", fps=10, size=(WIDTH, HEIGHT))
|
|
||||||
random.seed()
|
|
||||||
self.z = list(range(1, 101))
|
|
||||||
random.shuffle(self.z)
|
|
||||||
self.finished = False
|
|
||||||
self.tree = BinaryTree()
|
|
||||||
self.tree.get_height = lambda node: 0 if node is None else 1 + max(self.tree.get_height(node.left), self.tree.get_height(node.right))
|
|
||||||
self.height = self.tree.get_height(self.tree.root)
|
|
||||||
|
|
||||||
def update_game(self):
|
|
||||||
if not self.finished:
|
|
||||||
i = self.z.pop()
|
|
||||||
self.tree.insert(i)
|
|
||||||
self.height = self.tree.get_height(self.tree.root)
|
|
||||||
if len(self.z) == 0:
|
|
||||||
self.finished = True
|
|
||||||
return True
|
|
||||||
|
|
||||||
def draw_game(self):
|
|
||||||
self.screen.fill(WHITE)
|
|
||||||
if self.height > 0:
|
|
||||||
self.draw_tree(self.tree.root, WIDTH // 2, MARGIN, WIDTH // 4 - MARGIN)
|
|
||||||
super().draw_game()
|
|
||||||
|
|
||||||
def draw_tree(self, node, x, y, x_offset):
|
|
||||||
y_offset = (HEIGHT - (2 * MARGIN)) / self.height
|
|
||||||
if node is not None:
|
|
||||||
pygame.draw.circle(self.screen, BLUE, (x, y), 2)
|
|
||||||
if node.left is not None:
|
|
||||||
pygame.draw.line(self.screen, BLACK, (x, y), (x - x_offset, y + y_offset))
|
|
||||||
self.draw_tree(node.left, x - x_offset, y + y_offset, x_offset // 2)
|
|
||||||
if node.right is not None:
|
|
||||||
pygame.draw.line(self.screen, BLACK, (x, y), (x + x_offset, y + y_offset))
|
|
||||||
self.draw_tree(node.right, x + x_offset, y + y_offset, x_offset // 2)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
tree_game = BinTreeGame()
|
|
||||||
tree_game.run()
|
|
||||||
|
|
@ -18,5 +18,7 @@ class BinaryTreeNode(MemoryCell):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.value)
|
return str(self.value)
|
||||||
|
|
||||||
def graphviz_rep(self, row, col, dot):
|
def gv_rep(self, row, col):
|
||||||
dot.node(str(id(self)), label=str(self.value), pos=f"{col},{-row}!")
|
"""Returns the graphviz representation of the node."""
|
||||||
|
return f"{id(self)} [label=\"{self.value}\", pos=\"{col},{-row}!\"];\n"
|
||||||
|
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
from utils.memory_manager import MemoryManager
|
|
||||||
from utils.memory_array import MemoryArray
|
|
||||||
from utils.literal import Literal
|
|
||||||
from b_tree import BTree
|
|
||||||
from b_tree_node import BTreeNode
|
|
||||||
|
|
||||||
class MemoryManagerBTree(MemoryManager):
|
|
||||||
"""
|
|
||||||
Diese Klasse erweitert den MemoryManager, um spezifische Statistiken für B-Bäume zu speichern.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def count_loads():
|
|
||||||
return sum([cell.loaded_count for cell in MemoryManager().cells if isinstance(cell, BTreeNode)])
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def count_saves():
|
|
||||||
return sum([cell.saved_count for cell in MemoryManager().cells if isinstance(cell, BTreeNode)])
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def save_stats(count):
|
|
||||||
data = { "cells": MemoryManager.count_cells(),
|
|
||||||
"reads": MemoryManager.count_reads(),
|
|
||||||
"writes": MemoryManager.count_writes(),
|
|
||||||
"compares": MemoryManager.count_compares(),
|
|
||||||
"adds": MemoryManager.count_adds(),
|
|
||||||
"subs": MemoryManager.count_subs(),
|
|
||||||
"muls": MemoryManager.count_muls(),
|
|
||||||
"divs": MemoryManager.count_divs(),
|
|
||||||
"bitops": MemoryManager.count_bitops(),
|
|
||||||
"loads": MemoryManagerBTree.count_loads(),
|
|
||||||
"saves": MemoryManagerBTree.count_saves() }
|
|
||||||
MemoryManager.stats[count] = data
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def analyze_complexity(sizes):
|
|
||||||
"""
|
|
||||||
Analysiert die Komplexität
|
|
||||||
|
|
||||||
:param sizes: Eine Liste von Eingabegrößen für die Analyse.
|
|
||||||
"""
|
|
||||||
for size in sizes:
|
|
||||||
MemoryManager.purge() # Speicher zurücksetzen
|
|
||||||
tree = BTree(5)
|
|
||||||
random_array = MemoryArray.create_random_array(size, -100, 100)
|
|
||||||
for i in range(size-1):
|
|
||||||
tree.insert(int(random_array[Literal(i)]))
|
|
||||||
MemoryManager.reset()
|
|
||||||
tree.insert(int(random_array[Literal(size-1)]))
|
|
||||||
MemoryManagerBTree.save_stats(size)
|
|
||||||
|
|
||||||
MemoryManager.plot_stats(["cells", "compares", "loads", "saves"])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sizes = range(1, 1001, 2)
|
|
||||||
analyze_complexity(sizes)
|
|
@ -1,120 +0,0 @@
|
|||||||
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)}")
|
|
@ -1,29 +0,0 @@
|
|||||||
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)]) + ")"
|
|
Loading…
x
Reference in New Issue
Block a user