def quick_sort(z: AlgoDatArray, left: int, right: int): | def quick_sort(z: AlgoDatArray, left: int, right: int): | ||||
if left < right: | 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, left, q-1) | ||||
quick_sort(z, q+1, right) | quick_sort(z, q+1, right) | ||||
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() |
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() |
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() |
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() |