@@ -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) | |||
@@ -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() |
@@ -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() |
@@ -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() |
@@ -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() |