forked from hofmannol/AlgoDatSoSe25
Implemented AVL Insert, sort and some debugstuff to find weird pythonissues
This commit is contained in:
parent
552f226e76
commit
58f66fc1ff
@ -14,11 +14,8 @@ def timeMS(func, *args, **kwargs):
|
||||
|
||||
|
||||
from utils.memory_array import MemoryArray
|
||||
from utils.memory_cell import MemoryCell
|
||||
from utils.literal import Literal
|
||||
from utils.constants import MAX_VALUE
|
||||
from utils.memory_manager import MemoryManager
|
||||
from utils.memory_range import mrange
|
||||
from vorlesung.L05_binaere_baeume.bin_tree import BinaryTree
|
||||
from vorlesung.L05_binaere_baeume.bin_tree_node import BinaryTreeNode
|
||||
|
||||
@ -39,11 +36,15 @@ def analyze_complexity(fn, sizes):
|
||||
|
||||
lineAccumulator = []
|
||||
|
||||
# its not getting forwarded so we can not work with return. I will try glob vars to append the string
|
||||
# Returnvalue does not get forwarded so we can not work with return.
|
||||
# Will try glob vars to append the string
|
||||
# Signature: def print_node(node, indent=0, line=None):
|
||||
def clbk_graphvizify(toDecorate : BinaryTreeNode, indent=0, line=None):
|
||||
global lineAccumulator
|
||||
|
||||
if isinstance(toDecorate, AVLTreeNode):
|
||||
lineAccumulator.append(f"n_{id(toDecorate)} [label=\"{toDecorate.value}\\n{toDecorate.balanceFactor}\"]")
|
||||
else:
|
||||
lineAccumulator.append(f"n_{id(toDecorate)} [label={toDecorate.value}]")
|
||||
|
||||
# Create edges for nodes with Child (use l - r)
|
||||
@ -53,26 +54,193 @@ def clbk_graphvizify(toDecorate : BinaryTreeNode, indent=0, line=None):
|
||||
if toDecorate.right is not None:
|
||||
lineAccumulator.append(f"n_{id(toDecorate)} -> n_{id(toDecorate.right)}")
|
||||
|
||||
|
||||
def graphvizify() -> str:
|
||||
# Header
|
||||
result = "digraph {\n\t"
|
||||
# Body
|
||||
result += ('\n\t'.join(str(item) for item in lineAccumulator))
|
||||
# Foot
|
||||
# Footer
|
||||
result += "\n}"
|
||||
return result
|
||||
|
||||
class AVLTreeNode(BinaryTreeNode):
|
||||
def __init__(self, value):
|
||||
super().__init__(value)
|
||||
self.parentRef = None
|
||||
# Start balanced as we probably have no children right after insert
|
||||
self.balanceFactor = Literal(0)
|
||||
|
||||
def rightRotate(self, node) -> 'AVLTreeNode|None':
|
||||
if node is None:
|
||||
return None
|
||||
|
||||
oLeft = node.left;
|
||||
oLeft.parentRef = node.parentRef;
|
||||
node.left = oLeft.right;
|
||||
|
||||
if node.left is not None:
|
||||
node.left.parentRef = node;
|
||||
|
||||
oLeft.right = node;
|
||||
node.parentRef = oLeft;
|
||||
|
||||
if oLeft.parentRef is not None:
|
||||
if oLeft.parentRef.right is node:
|
||||
oLeft.parentRef.right = oLeft;
|
||||
elif oLeft.parentRef.left is node:
|
||||
oLeft.parentRef.left = oLeft;
|
||||
|
||||
node.getSetBalanceFactor()
|
||||
oLeft.getSetBalanceFactor()
|
||||
|
||||
return oLeft
|
||||
|
||||
def leftRotate(self, node) -> 'AVLTreeNode|None':
|
||||
if node is None:
|
||||
return None
|
||||
|
||||
oRight = node.right
|
||||
oRight.parentRef = node.parentRef
|
||||
node.right = oRight.left
|
||||
|
||||
if node.right is not None:
|
||||
node.right.parentRef = node
|
||||
|
||||
oRight.left = node
|
||||
node.parentRef = oRight
|
||||
|
||||
if oRight.parentRef is not None:
|
||||
if oRight.parentRef.right is node:
|
||||
oRight.parentRef.right = oRight
|
||||
elif oRight.parentRef.left is node:
|
||||
oRight.parentRef.left = oRight
|
||||
|
||||
node.getSetBalanceFactor()
|
||||
oRight.getSetBalanceFactor()
|
||||
|
||||
return oRight
|
||||
|
||||
def getSetBalanceFactor(self) -> Literal:
|
||||
leftHeight = self.left.height() if self.left else 0
|
||||
rightHeight = self.right.height() if self.right else 0
|
||||
self.balanceFactor = Literal(rightHeight - leftHeight)
|
||||
return self.balanceFactor
|
||||
|
||||
def rightLeftRotate(self, node) -> 'AVLTreeNode|None':
|
||||
node.right = self.rightRotate(node.right)
|
||||
return self.leftRotate(node)
|
||||
|
||||
def leftRightRotate(self, node) -> 'AVLTreeNode|None':
|
||||
node.left = self.leftRotate(node.left)
|
||||
return self.rightRotate(node)
|
||||
|
||||
|
||||
def debugTraverse(node, source=1):
|
||||
if node is None:
|
||||
return None
|
||||
logger.debug(f"{node.value} {node.getSetBalanceFactor()} {source}")
|
||||
debugTraverse(node.left, 10);
|
||||
debugTraverse(node.right, 20);
|
||||
|
||||
|
||||
class AVLTree(BinaryTree):
|
||||
# @override
|
||||
def new_node(self, value) -> AVLTreeNode:
|
||||
return AVLTreeNode(value)
|
||||
|
||||
def balanceAVLTree(self, node : AVLTreeNode):
|
||||
# balance < -1 means imbalance to the left, > 1 means imbalance to the right
|
||||
logger.debug("in")
|
||||
if node is None:
|
||||
return None
|
||||
logger.debug("out")
|
||||
|
||||
node.getSetBalanceFactor()
|
||||
logger.debug(f"Parent Balancing for {node.value} -> {node.balanceFactor} {node.left.height() if node.left else None} and {node.right.height() if node.right else None}")
|
||||
|
||||
# imbalance to left -> If we enter this we cannot LOGICALLY have a left=None node -> No need to chekc
|
||||
if node.balanceFactor < Literal(-1):
|
||||
# Left-Left
|
||||
if node.left.balanceFactor <= Literal(0): # type: ignore -> Ignoring pywright error, see comment above
|
||||
# Wow, this syntax is sketchy ^^
|
||||
# TODO Maybe declare as static if python supports this? Or just leaf param be?
|
||||
logger.debug("rr")
|
||||
node = node.rightRotate(node)
|
||||
# Left-Right
|
||||
else:
|
||||
# TODO Maybe declare as static if python supports this? Or just leaf param be?
|
||||
logger.debug("lrr")
|
||||
node = node.leftRightRotate(node)
|
||||
|
||||
# Right heavy
|
||||
# imbalance to right -> If we enter this we cannot LOGICALLY have a right=None node -> No need to chekc
|
||||
if node.balanceFactor > Literal(1):
|
||||
# Right-Right case
|
||||
if node.right.balanceFactor >= Literal(0): # type: ignore -> Ignoring pywright error, see comment above
|
||||
# TODO Maybe declare as static if python supports this? Or just leaf param be?
|
||||
logger.debug("lr")
|
||||
node = node.leftRotate(node)
|
||||
# Right-Left case
|
||||
else:
|
||||
# TODO Maybe declare as static if python supports this? Or just leaf param be?
|
||||
logger.debug("rlr")
|
||||
node = node.rightLeftRotate(node)
|
||||
|
||||
logger.debug(f"Reached {node.parentRef}")
|
||||
if node.parentRef is not None:
|
||||
logger.debug(f"Calling again for {node.parentRef.value}");
|
||||
self.balanceAVLTree(node.parentRef);
|
||||
else:
|
||||
self.root = node;
|
||||
|
||||
# Node is balanced
|
||||
return node
|
||||
|
||||
# @override
|
||||
def insert(self, value):
|
||||
node, parent = super().insert(value)
|
||||
# NOTE Python does not have a Problem with NOT tellin us that we override something important
|
||||
# or something that does not exist.... This Makes for AWESOME debugging .... ... ...
|
||||
node.parentRef = parent
|
||||
|
||||
if parent:
|
||||
node = self.balanceAVLTree(node.parentRef)
|
||||
|
||||
return node, parent
|
||||
|
||||
if __name__ == '__main__':
|
||||
tree = BinaryTree()
|
||||
values = [5, 3, 7, 2, 4, 6, 5, 8]
|
||||
tree = AVLTree()
|
||||
|
||||
### Force RR
|
||||
# testData = [30, 20, 10];
|
||||
# for value in testData:
|
||||
# tree.insert(MemoryCell(value));
|
||||
|
||||
### Force LR
|
||||
# testData = [10, 20, 30];
|
||||
# for value in testData:
|
||||
# tree.insert(MemoryCell(value));
|
||||
|
||||
### Force LRR
|
||||
# testData = [30, 10, 20]
|
||||
# for value in testData:
|
||||
# tree.insert(MemoryCell(value))
|
||||
|
||||
### Force RLR
|
||||
# testData = [10, 30, 20]
|
||||
# for value in testData:
|
||||
# tree.insert(MemoryCell(value))
|
||||
|
||||
# Force rebuild of our balanceFactor indices...
|
||||
# debugTraverse(tree.root)
|
||||
|
||||
binTreeData = MemoryArray.create_array_from_file("data/seq0.txt")
|
||||
for value in binTreeData:
|
||||
tree.insert(value)
|
||||
|
||||
# for value in values:
|
||||
# tree.insert(value)
|
||||
|
||||
lineAccumulator.clear();
|
||||
tree.in_order_traversal(clbk_graphvizify)
|
||||
# tree.tree_structure_traversal(clbk_graphvizify)
|
||||
print(graphvizify())
|
||||
|
Loading…
x
Reference in New Issue
Block a user