AI/Unit 1/Umaretiya_r_U1_L3.py
2020-12-15 03:02:42 -05:00

164 lines
4.3 KiB
Python

# Name: Rushil Umaretiya
# Date: 10/01/2020
import random
class HeapPriorityQueue():
def __init__(self):
self.queue = ["dummy"] # we do not use index 0 for easy index calulation
self.current = 1 # to make this object iterable
def next(self): # define what __next__ does
if self.current >=len(self.queue):
self.current = 1 # to restart iteration later
raise StopIteration
out = self.queue[self.current]
self.current += 1
return out
def __iter__(self):
return self
__next__ = next
def isEmpty(self):
return len(self.queue) <= 1 # b/c index 0 is dummy
def swap(self, a, b):
self.queue[a], self.queue[b] = self.queue[b], self.queue[a]
# Add a value to the heap_pq
def push(self, value):
self.queue.append(value)
# write more code here to keep the min-heap property
self.heapUp(len(self.queue)-1)
# helper method for push
def heapUp(self, k):
if k <= 1:
return
if len(self.queue) % 2 == 1 and k == len(self.queue) - 1: # no sibling
if self.queue[k//2] > self.queue[k]:
self.swap(k, k//2)
self.heapUp(k//2)
return
if k % 2 == 0:
parent, sibling = k//2, k+1
else:
parent, sibling = k//2, k-1
if self.queue[k] > self.queue[sibling]:
child = sibling
else:
child = k
if self.queue[parent] > self.queue[child]:
self.swap(child, parent)
self.heapUp(parent)
# helper method for reheap and pop
def heapDown(self, k, size):
left, right = 2*k, 2*k+1
if left == size and self.queue[k] > self.queue[size]: # One child
self.swap(k, left)
elif right <= size:
child = (left if self.queue[left] < self.queue[right] else right)
if self.queue[k] > self.queue[child]:
self.swap(k, child)
self.heapDown(child, size)
# make the queue as a min-heap
def reheap(self):
if self.isEmpty():
return -1
for k in range((len(self.queue)-1)//2, 0, -1):
self.heapUp(k)
# remove the min value (root of the heap)
# return the removed value
def pop(self):
if self.isEmpty():
return -1
self.swap (1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(1, len(self.queue) - 1)
return val
# remove a value at the given index (assume index 0 is the root)
# return the removed value
def remove(self, index):
if self.isEmpty():
return -1
if len (self.queue) == 2:
val = self.queue.pop()
self.queue = []
return val
self.swap (index + 1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(index + 1, len(self.queue) - 1)
return val
# This method is for testing. Do not change it.
def isHeap(heap, k):
left, right = 2*k, 2*k+1
if left == len(heap): return True
elif len(heap) == right and heap[k] > heap[left]: return False
elif right < len(heap):
if (heap[k] > heap[left] or heap[k] > heap[right]): return False
else: return isHeap(heap, left) and isHeap(heap, right)
return True
# This method is for testing. Do not change it.
def main():
pq = HeapPriorityQueue() # create a HeapPriorityQueue object
print ("Check if dummy 0 is still dummy:", pq.queue[0])
# assign random integers into the pq
for i in range(20):
t = random.randint(10, 99)
print (t, end=" ")
pq.push(t)
print ()
# print the pq which is a min-heap
for x in pq:
print (x, end=" ")
print()
# remove test
print ("Index 4 is removed:", pq.remove(4))
# check if pq is a min-heap
for x in pq:
print (x, end=" ")
print("\nIs a min-heap?", isHeap(pq.queue, 1))
temp = []
while not pq.isEmpty():
temp.append(pq.pop())
print (temp[-1], end=" ")
print ("\nIn ascending order?", temp == sorted(temp))
if __name__ == '__main__':
main()