Browse Source

lecture 5

master
Oliver Hofmann 8 months ago
parent
commit
5bb8b62fa9

+ 2
- 2
SoSe24/lec03_sort_alg/quick_sort.py View File

@@ -54,8 +54,8 @@ def median_pivot(z: AlgoDatArray, left: int, right: int) -> int:

def quick_sort(z: AlgoDatArray, left: int, right: int):
if left < right:
q = partition(z, left, right)
#q = median_pivot(z, left, right)
#q = partition(z, left, right)
q = median_pivot(z, left, right)
quick_sort(z, left, q-1)
quick_sort(z, q+1, right)


+ 111
- 0
SoSe24/lec04_trees/avl_tree.py View File

@@ -0,0 +1,111 @@
from SoSe24.algodat.foundation import AlgoDatArray, AlgoDatValue, read_int_sequence
from SoSe24.lec04_trees.bin_tree import BinTree, BinTreeNode
from time import perf_counter as pfc

class AVLTreeNode(BinTreeNode):
def __init__(self, value: AlgoDatValue):
super().__init__(value)
self.parent = None
self.balance = 0

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) -> BinTreeNode:
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 == 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) -> BinTreeNode:
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 == 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) -> BinTreeNode:
self.right = self.right.right_rotate()
return self.left_rotate()

def left_right_rotate(self) -> BinTreeNode:
self.left = self.left.left_rotate()
return self.right_rotate()

class AVLTree(BinTree):

def new_node(self, value: AlgoDatValue):
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: AlgoDatValue):
node, parent = super().insert(value)
node.parent = parent
if parent:
self.balance(parent)
return node, parent

def delete(self, value: AlgoDatValue):
node, parent = super().delete(value)
if node:
node.parent = parent
if parent:
self.balance(parent)



if __name__ == "__main__":
z = read_int_sequence("../../seq0.txt")
print(z, len(z))
start = pfc()
tree = AVLTree()
for i in z:
tree.insert(i)
tree.walk()
tree.tree_walk()
tree.levelwalk()
#tree.graph_walk()
tree.delete(AlgoDatValue(46))
tree.delete(AlgoDatValue(48))
tree.graph_walk()
print(f"Dauer: {pfc() - start:.4f}s")
AlgoDatValue.summary()

+ 29
- 0
SoSe24/lec04_trees/avl_tree_plot.py View File

@@ -0,0 +1,29 @@
from SoSe24.algodat.foundation import AlgoDatArray, AlgoDatValue, read_int_sequence, read_int_sequence_limited
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import avl_tree as avl

if __name__ == "__main__":
filename = "../../seq3_sorted.txt"
#filename = "../../seq3.txt"
dummy = read_int_sequence(filename)
n = len(dummy)
step = n // 100

memory_values = []
compare_values = []

for right_end in range(1, n, step):
AlgoDatValue.reset()
z = read_int_sequence_limited(filename, right_end)
tree = avl.AVLTree()
for i in z:
tree.insert(i)
memory_values.append(AlgoDatValue.memory)
compare_values.append(AlgoDatValue.compare)

plt.plot(range(1, n, step), memory_values, 'b', label='Memory')
plt.plot(range(1, n, step), compare_values, 'r', label='Compare')
plt.legend()
plt.show()

+ 171
- 0
SoSe24/lec04_trees/bin_tree.py View File

@@ -0,0 +1,171 @@
from SoSe24.algodat.foundation import AlgoDatArray, AlgoDatValue, read_int_sequence
from time import perf_counter as pfc

class BinTreeNode:
def __init__(self, value: AlgoDatValue):
self.value = value
self.left = None
self.right = None

def __str__(self):
return f"{self.value}"

def height(self) -> int:
left_height = self.left.height() if self.left else 0
right_height = self.right.height() if self.right else 0
return 1 + max(left_height, right_height)



class BinTree:
def __init__(self):
self.root = None

def new_node(self, value: AlgoDatValue) -> BinTreeNode:
return BinTreeNode(value)

def insert(self, value: AlgoDatValue) -> (BinTreeNode, BinTreeNode):
if not self.root:
self.root = self.new_node(value)
return self.root, None

current = self.root
while True:
if value < current.value:
if current.left:
current = current.left
else:
current.left = self.new_node(value)
return current.left, current
elif value >= current.value:
if current.right:
current = current.right
else:
current.right = self.new_node(value)
return current.right, current
else:
return None, None

def search(self, value: AlgoDatValue) -> BinTreeNode:
current = self.root
while current:
if value < current.value:
current = current.left
elif value > current.value:
current = current.right
else:
return current
return None

def delete(self, value: AlgoDatValue):
parent = None
current = self.root
while current:
if value < current.value:
parent = current
current = current.left
elif value > current.value:
parent = current
current = current.right
else:
break
else:
return None, None

if current.left and current.right:
parent = current
successor = current.right
while successor.left:
parent = successor
successor = successor.left
current.value.value = successor.value.value
current = successor

if current.left:
child = current.left
else:
child = current.right

if not parent:
self.root = child
return child, None
elif parent.left == current:
parent.left = child
return child, parent
else:
parent.right = child
return child, parent

def walk(self): # in-order
print("[ ", end="")
self.walk_recursive(self.root, 0, 0)
print(" ]")


def graph_walk(self):
self.leaf_counter = 0
with open("../../graph.gv", "w") as file:
file.write("digraph BST {\n")
file.write(" node [fontname=\"Arial\"];\n")
self.graph_walk_recursive(self.root, file)
file.write("}")

def graph_walk_recursive(self, current, file):
if current is not None:
if current.left:
file.write(f"{current.value} -> {current.left.value}; \n")
self.graph_walk_recursive(current.left, file)
else:
file.write(f"left{self.leaf_counter} [shape=point]; \n")
file.write(f"{current.value} -> left{self.leaf_counter}; \n")
self.leaf_counter += 1
if current.right:
file.write(f"{current.value} -> {current.right.value}; \n")
self.graph_walk_recursive(current.right, file)
else:
file.write(f"right{self.leaf_counter} [shape=point]; \n")
file.write(f"{current.value} -> right{self.leaf_counter}; \n")
self.leaf_counter += 1


def tree_walk(self):
self.walk_recursive(self.root, 0, 1)

def walk_recursive(self, node: BinTreeNode, level = 0, increase = 1):
if node:
if increase >= 1:
end = "\n"
else:
end = " "
self.walk_recursive(node.left, level+increase, increase)
print(" "*level*3 + str(node.value), end=end)
self.walk_recursive(node.right, level+increase, increase)

def levelwalk(self):
if self.root is None:
return
queue = [self.root]
while queue:
current = queue.pop(0)
print(current.value, end=" ")
if current.left:
queue.append(current.left)
if current.right:
queue.append(current.right)
print()


if __name__ == "__main__":
z = read_int_sequence("../../seq0.txt")
print(z, len(z))
start = pfc()
tree = BinTree()
for i in z:
tree.insert(i)
tree.walk()
tree.tree_walk()
tree.levelwalk()
tree.delete(AlgoDatValue(46))
tree.graph_walk()
print(f"Dauer: {pfc() - start:.4f}s")
AlgoDatValue.summary()

+ 29
- 0
SoSe24/lec04_trees/bin_tree_plot.py View File

@@ -0,0 +1,29 @@
from SoSe24.algodat.foundation import AlgoDatArray, AlgoDatValue, read_int_sequence, read_int_sequence_limited
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import bin_tree as bt

if __name__ == "__main__":
filename = "../../seq3_sorted.txt"
#filename = "../../seq3.txt"
dummy = read_int_sequence(filename)
n = len(dummy)
step = n // 100

memory_values = []
compare_values = []

for right_end in range(1, n, step):
AlgoDatValue.reset()
z = read_int_sequence_limited(filename, right_end)
tree = bt.BinTree()
for i in z:
tree.insert(i)
memory_values.append(AlgoDatValue.memory)
compare_values.append(AlgoDatValue.compare)

plt.plot(range(1, n, step), memory_values, 'b', label='Memory')
plt.plot(range(1, n, step), compare_values, 'r', label='Compare')
plt.legend()
plt.show()

Loading…
Cancel
Save