AlgoDatSoSe25/schoeffelbe/priorityQueue.py

225 lines
6.5 KiB
Python

from utils.memory_array import MemoryArray
from utils.memory_cell import MemoryCell
from utils.literal import Literal
from utils.constants import MIN_VALUE
from utils.memory_manager import MemoryManager
from utils.memory_range import mrange
# Impl of MemoryArray says we cant add our own Datatypes beside Literal and List
# BUUUUT we can just wrap our Datatype in a List :-)
class HeapEntry:
def __init__(self, item, priority=1):
self.data = MemoryArray(Literal(2))
# 0: Content, 1: Prio
self.data[Literal(0)] = Literal(item)
self.data[Literal(1)] = Literal(priority)
def getItem(self):
return self.data[Literal(0)]
def getPriority(self):
return self.data[Literal(1)]
def setPriority(self, priority):
self.data[Literal(1)] = Literal(priority)
def __lt__(self, other):
if other is None:
return True
if isinstance(other, (int, float)):
return self.getPriority().value > other
return self.getPriority() > other.getPriority()
def __gt__(self, other):
if other is None:
return False
if isinstance(other, (int, float)):
return self.getPriority().value < other
return self.getPriority() < other.getPriority()
def __eq__(self, other):
return self.getPriority() == other.getPriority()
def __str__(self):
return f"({self.getItem()}, prio={self.getPriority()})"
class PriorityQueue:
def __init__(self, max_size : Literal = Literal(100)):
self.heap = MemoryArray(max_size)
self.size = MemoryCell(0)
def parent(self, i: Literal) -> Literal:
return MemoryCell(i.pred()) // Literal(2)
def leftChild(self, i: Literal) -> Literal:
return MemoryCell(MemoryCell(2) * i) + Literal(1)
def rightChild(self, i: Literal) -> Literal:
return MemoryCell(MemoryCell(2) * i) + Literal(2)
def swap(self, i: Literal, j: Literal):
tmp_i = self.heap[i].value
tmp_j = self.heap[j].value
self.heap[i].set(tmp_j)
self.heap[j].set(tmp_i)
def max_heapify(self, i: Literal):
left = self.leftChild(i)
right = self.rightChild(i)
largest = i
if left < self.size and self.heap[left] > self.heap[largest]:
largest = left
if right < self.size and self.heap[right] > self.heap[largest]:
largest = right
if largest != i:
self.swap(i, largest)
self.max_heapify(largest)
def insert(self, entry : HeapEntry):
if self.size >= self.heap.length():
raise IndexError("Heap full")
i = self.size
self.heap[i].set([entry])
self.size += Literal(1)
currentNode = self.heap[i]
parentNode : Literal = self.heap[self.parent(i)]
print(currentNode)
print(parentNode)
while i > Literal(0) and self.heap[self.parent(i)] < self.heap[i]:
self.swap(i, self.parent(i))
i = self.parent(i)
def pop(self):
if self.is_empty():
raise IndexError("Queue is empty!")
max_item = self.heap[Literal(0)]
self.heap[Literal(0)] = self.heap[self.size - Literal(1)]
self.size -= Literal(1)
self.max_heapify(Literal(0))
return max_item
def peek(self):
if self.is_empty():
raise IndexError("Queue is empty")
return self.heap[Literal(0)]
def is_empty(self):
return self.size == Literal(0)
def __len__(self):
"""Gibt die Anzahl der Elemente in der Warteschlange zurück."""
return self.size
def dummify(method):
match method.lower():
case "add":
tmp = MemoryCell(1) + Literal(1);
case "cmp":
tmp = MemoryCell(1) > Literal(1);
# Had to adapt different Approach
# Had to resort to using primite Types as I do not know the language good enough to get my original
# approach working and ran out of time
class PriorityQueue_Primitive:
def __init__(self, max_size=100):
self.heap = [None] * max_size
self.size = 0
def parent(self, i):
return (i - 1) // 2
def leftChild(self, i):
return 2 * i + 1
def rightChild(self, i):
return 2 * i + 2
def swap(self, i, j):
self.heap[i], self.heap[j] = self.heap[j], self.heap[i]
def maxHeapify(self, i):
left = self.leftChild(i)
right = self.rightChild(i)
largest = i
if left < self.size and self.heap[left] is not None:
if self.heap[largest] is None or self.heap[left] > self.heap[largest]:
largest = left
if right < self.size and self.heap[right] is not None:
if self.heap[largest] is None or self.heap[right] > self.heap[largest]:
largest = right
if largest != i:
self.swap(i, largest)
self.maxHeapify(largest)
def insert(self, entry):
if self.size >= len(self.heap):
raise IndexError("Heap full")
i = self.size
self.heap[i] = entry
self.size += 1
while i > 0:
parent = self.parent(i)
# Overloaded -> LSP not working quite right, but Interpreter does
if self.heap[parent] is None or self.heap[i] > self.heap[parent]:
self.swap(i, parent)
i = parent
else:
break
def pop(self):
if self.is_empty():
raise IndexError("Queue is empty!")
max_entry = self.heap[0]
self.heap[0] = self.heap[self.size - 1]
self.heap[self.size - 1] = None
self.size -= 1
if not self.is_empty():
self.maxHeapify(0)
return max_entry
def peek(self):
if self.is_empty():
raise IndexError("Queue is empty")
return self.heap[0]
def is_empty(self):
return self.size == 0
def __len__(self):
return self.size
if __name__ == '__main__':
pq = PriorityQueue_Primitive()
assert(pq.size == 0 and pq.is_empty())
test = HeapEntry("A", 2)
print(test)
a = MemoryArray([test])
print(a)
print(a[Literal(0)])
pq.insert(HeapEntry("D", 3));
pq.insert(HeapEntry("A", 4));
pq.insert(HeapEntry("T", 2));
print(pq.pop())
print(pq.pop())
print(pq.pop())