This commit is contained in:
Oliver Hofmann 2025-04-15 13:59:01 +02:00
commit abcfc7ab1b
4 changed files with 253 additions and 4 deletions

View File

@ -0,0 +1,150 @@
from utils.memory_array import MemoryArray
from utils.memory_cell import MemoryCell
from utils.memory_manager import MemoryManager
from utils.literal import Literal
import random
class PriorityQueue:
def __init__(self, size: Literal):
self.items = MemoryArray(size)
self.heapsize = MemoryCell(0)
def __len__(self):
return self.heapsize.value
def insert(self, item: MemoryCell):
if self.heapsize == self.items.length():
raise Exception("Queue is full")
self.heapsize.set(self.heapsize.succ())
self.items[adjust_index(self.heapsize)].set(item.value)
heapyfy_up(self.items, self.heapsize)
def pop(self) -> MemoryCell | None:
if self.is_empty():
return None
result = MemoryCell(self.items[Literal(0)])
self.heapsize.set(self.heapsize.pred())
if self.heapsize > Literal(1):
swap(self.items, 0, int(self.heapsize))
max_heapyfy(self.items, Literal(1), self.heapsize)
return result
def peek(self) -> MemoryCell | None:
if self.is_empty():
return None
return MemoryCell(self.items[Literal(0)])
def is_empty(self) -> bool:
return self.heapsize == Literal(0)
def __str__(self):
result = "[ "
for i, cell in enumerate(self.items.cells):
if i == int(self.heapsize):
result += "| "
result += str(cell) + " "
result += "]"
return result
def left_child(i: Literal):
return Literal(2 * int(i))
def right_child(i: Literal):
return Literal(2 * int(i) + 1)
def adjust_index(i: Literal):
return i.pred()
def heapyfy_up(z: MemoryArray, i: Literal):
if i == Literal(1):
return
parent = Literal(int(i) // 2)
if z[adjust_index(parent)] >= z[adjust_index(i)]:
return
swap(z, int(i)-1, int(parent)-1)
heapyfy_up(z, parent)
def max_heapyfy(z: MemoryArray, i: Literal, heapsize: Literal):
l = left_child(i)
r = right_child(i)
with MemoryCell(i) as max_value:
if l <= heapsize and z[adjust_index(l)] > z[adjust_index(i)]:
max_value.set(l)
if r <= heapsize and z[adjust_index(r)] > z[adjust_index(max_value)]:
max_value.set(r)
if max_value != i:
swap(z, int(i)-1, int(max_value)-1)
max_heapyfy(z, max_value, heapsize)
def swap(z: MemoryArray, i: int, j: int):
tmp = z[Literal(i)].value
z[Literal(i)] = z[Literal(j)]
z[Literal(j)].set(tmp)
def analyze_complexity_insert(sizes, presorted=False):
"""
Analysiert die Komplexität der Insert-Funktion.
"""
for size in sizes:
MemoryManager().purge() # Speicher zurücksetzen
pq = PriorityQueue(Literal(size))
insert_list = [random.randint(-100, 100) for _ in range(size)]
if presorted:
insert_list.sort()
for insert_value in insert_list[:-1]:
pq.insert(MemoryCell(insert_value))
MemoryManager().reset()
pq.insert(MemoryCell(insert_list[-1]))
MemoryManager.save_stats(size)
MemoryManager.plot_stats(["cells", "compares", "writes"])
def analyze_complexity_pop(sizes, presorted=False):
"""
Analysiert die Komplexität der Pop-Funktion.
"""
for size in sizes:
MemoryManager().purge() # Speicher zurücksetzen
pq = PriorityQueue(Literal(size))
insert_list = [random.randint(-100, 100) for _ in range(size)]
if presorted:
insert_list.sort()
for insert_value in insert_list:
pq.insert(MemoryCell(insert_value))
MemoryManager().reset()
pq.pop()
MemoryManager.save_stats(size)
MemoryManager.plot_stats(["cells", "compares", "writes"])
if __name__ == '__main__':
length = Literal(10)
pq = PriorityQueue(length)
for i in range(10):
space_left = int(length) - len(pq)
if space_left > 0:
insert_count = random.randint(1, space_left)
insert_sequence = [random.randint(1, int(length)) for _ in range(insert_count)]
print(f"-> {insert_sequence}")
for j in insert_sequence:
pq.insert(MemoryCell(j))
print(f"{pq}")
if not pq.is_empty():
pop_count = random.randint(1, len(pq))
output_sequence = [int(pq.pop()) for _ in range(pop_count)]
print(f"<- {output_sequence}")
print(f"{pq}")
sizes = range(10, 501, 5)
analyze_complexity_insert(sizes, presorted=True)
analyze_complexity_pop(sizes, presorted=True)

View File

@ -0,0 +1,93 @@
from utils.memory_array import MemoryArray
from utils.memory_cell import MemoryCell
from utils.memory_manager import MemoryManager
from utils.literal import Literal
def quick_sort_stepwise(z: MemoryArray, l: Literal, r: Literal):
if l < r:
q = partition(z, l, r)
yield z
yield from quick_sort_stepwise(z, l, q.pred())
yield from quick_sort_stepwise(z, q.succ(), r)
yield z
def partition(z: MemoryArray, l: Literal, r: Literal):
p = mid_index(z, l, r, Literal((int(l)+int(r))//2))
swap(z, p, r)
with MemoryCell(z[r]) as pivot, MemoryCell(l) as i, MemoryCell(r.pred()) as j:
while i < j:
while z[i] < pivot:
i.set(i.succ())
while j > l and z[j] >= pivot:
j.set(j.pred())
if i < j:
swap(z, int(i), int(j))
i.set(i.succ())
j.set(j.pred())
if i == j and z[i] < pivot:
i.set(i.succ())
if z[i] != pivot:
swap(z, int(i), int(r))
return Literal(i)
def mid_index(z: MemoryArray, i1, i2, i3):
if z[i1] < z[i2] < z[i3]:
return i2
elif z[i3] < z[i2] < z[i1]:
return i2
elif z[i2] < z[i1] < z[i3]:
return i1
elif z[i3] < z[i1] < z[i2]:
return i1
else:
return i3
def quick_sort(z: MemoryArray, l: Literal = None, r: Literal = None):
if l is None:
l = Literal(0)
if r is None:
r = z.length().pred()
sort_generator = quick_sort_stepwise(z, l, r)
while True:
try:
next(sort_generator)
except StopIteration:
break
def sort_file(filename, sort_func):
z = MemoryArray.create_array_from_file(filename)
sort_func(z)
return z
def analyze_complexity(sort_func, sizes, presorted=False):
"""
Analysiert die Komplexität einer Sortierfunktion.
:param sort_func: Die Funktion, die analysiert wird.
:param sizes: Eine Liste von Eingabegrößen für die Analyse.
"""
for size in sizes:
MemoryManager.purge() # Speicher zurücksetzen
if presorted:
random_array = MemoryArray.create_sorted_array(size)
else:
random_array = MemoryArray.create_random_array(size, -100, 100)
sort_func(random_array)
MemoryManager.save_stats(size)
MemoryManager.plot_stats(["cells", "compares", "writes"])
def swap(z: MemoryArray, i: int, j: int):
tmp = z[Literal(i)].value
z[Literal(i)] = z[Literal(j)]
z[Literal(j)].set(tmp)
if __name__ == '__main__':
sizes = range(10, 101, 5)
analyze_complexity(quick_sort, sizes)
analyze_complexity(quick_sort, sizes, True)

View File

@ -102,6 +102,13 @@ class MemoryArray:
a.reset_counters()
return a
def __str__(self):
result = "[ "
for cell in self.cells:
result += str(cell) + ", "
result += "]"
return result
if __name__ == "__main__":
import random

View File

@ -5,7 +5,6 @@ from utils.memory_range import mrange
from utils.literal import Literal
def quick_sort_stepwise(z: MemoryArray, l: Literal, r: Literal):
n = z.length()
if l < r:
q = partition(z, l, r)
yield z
@ -77,6 +76,6 @@ def swap(z: MemoryArray, i: int, j: int):
if __name__ == '__main__':
sizes = range(10, 101, 10)
analyze_complexity(quick_sort, sizes)
# analyze_complexity(quick_sort, sizes, True)
sizes = range(10, 101, 5)
#analyze_complexity(quick_sort, sizes)
analyze_complexity(quick_sort, sizes, True)