# 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()