forked from hofmannol/AlgoDatSoSe25
AVL implementation
This commit is contained in:
parent
326286128c
commit
ac7068d26c
12
praktika/05_avl_baum/gv_avl_tree.py
Normal file
12
praktika/05_avl_baum/gv_avl_tree.py
Normal file
@ -0,0 +1,12 @@
|
||||
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()
|
||||
|
12
praktika/05_avl_baum/gv_binary_tree.py
Normal file
12
praktika/05_avl_baum/gv_binary_tree.py
Normal file
@ -0,0 +1,12 @@
|
||||
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()
|
||||
|
26
vorlesung/L05_binaere_baeume/analyze_avl_tree.py
Normal file
26
vorlesung/L05_binaere_baeume/analyze_avl_tree.py
Normal file
@ -0,0 +1,26 @@
|
||||
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)
|
88
vorlesung/L05_binaere_baeume/avl_tree.py
Normal file
88
vorlesung/L05_binaere_baeume/avl_tree.py
Normal file
@ -0,0 +1,88 @@
|
||||
from vorlesung.L05_binaere_baeume.avl_tree_node import AVLTreeNode
|
||||
from vorlesung.L05_binaere_baeume.bin_tree import BinaryTree
|
||||
|
||||
|
||||
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
|
||||
# self.check_circle(self.root)
|
||||
|
||||
def insert(self, value):
|
||||
node, parent = super().insert(value)
|
||||
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 check_circle(self, node: AVLTreeNode, check_nodes = []):
|
||||
if node is None:
|
||||
return
|
||||
if id(node) in check_nodes:
|
||||
print("Circle detected")
|
||||
return
|
||||
self.check_circle(node.left, check_nodes + [id(node)])
|
||||
self.check_circle(node.right, check_nodes + [id(node)])
|
||||
|
||||
|
||||
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]
|
||||
|
||||
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)
|
62
vorlesung/L05_binaere_baeume/avl_tree_node.py
Normal file
62
vorlesung/L05_binaere_baeume/avl_tree_node.py
Normal file
@ -0,0 +1,62 @@
|
||||
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 gv_rep(self, row, col):
|
||||
"""Returns the graphviz representation of the node."""
|
||||
return f"{id(self)} [label=\"{self.value}\", pos=\"{col},{-row}!\", xlabel=\"{self.balance}\"];\n"
|
||||
|
||||
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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user