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