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"]) 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)