def heapsort(array): """Implements heapsort in-place using heap.Heap. Insert all the values in (via heapify in O(n) ) and the read them out in max order, inserting into the correct place in the orig list. This uses an additional O(n) space since we create another copy in the Heap. We could do this in place if the heap tracked the max heap size separate from the max array size """ heapy = Heap(array) for i in reversed(range(len(array))): array[i] = heapy.extract_max()
def shortest_path(graph, src, dest): if src == dest: return [src], 0 dist = traverse(graph, Heap([([src], 0)], cmp_frontier), dest) if not dist: print "No path form %s to %s" % (src, dest) return print "The min distance from %s to %s is %s" % (src, dest, dist) return dist
def __init__(self, **kwargs): """ Initialize the Queue """ list = kwargs.get('list', []) cmprator = kwargs.get('cmprator', lib.utils.get_def_cmprator()) self._debug = kwargs.get('debug', 0) self.elem_key_handler = kwargs.get('elem_key_handler', self.def_elem_key_handler) self.id_to_idx_map = {} self.heap = Heap( list = list, cmprator = cmprator, debug = self._debug )
class Max_Pri_Queue: def def_elem_key_handler(self, elem): return elem def __init__(self, **kwargs): """ Initialize the Queue """ list = kwargs.get('list', []) cmprator = kwargs.get('cmprator', lib.utils.get_def_cmprator()) self._debug = kwargs.get('debug', 0) self.elem_key_handler = kwargs.get('elem_key_handler', self.def_elem_key_handler) self.id_to_idx_map = {} self.heap = Heap( list = list, cmprator = cmprator, debug = self._debug ) @property def debug(self): return self._debug def maximum(self): """ Find elem whose key has max val in the queue """ if not self.heap.heapsize > 0: raise ex.exceptions.HeapSizeZero("Heap empty") return self.heap.read(0) def update_id_idx_map(self, start_idx = 0): """ Update the internal id to heap index map """ heapsize = self.heap.heapsize if not start_idx <= heapsize: raise ex.exceptions.BadIndexAccess( "Cannot go beyond heapsize idx " + str(heapsize) ) curr_idx = start_idx while curr_idx < heapsize: curr_id = self.heap.read(curr_idx) self.id_to_idx_map[curr_id] = curr_idx curr_idx += 1 return True def swap_nodes(self, idx1, idx2): """ Swap heap nodes """ tmp = self.heap.read(idx1) self.heap.write(idx1, self.heap.read(idx2)) self.heap.write(idx2, tmp) id1 = self.heap.read(idx1) id2 = self.heap.read(idx2) self.id_to_idx_map[id1] = idx1 self.id_to_idx_map[id2] = idx2 return True def update_key(self, id, new_key, op = 'inc'): """ Update key of element from k to new_k provided k > new_k """ # cannot increase key if heap empty idx = self.id_to_idx_map[id] heapsize = self.heap.heapsize if not heapsize > 0: raise ex.exceptions.HeapSizeZero("Heap empty") if not idx < heapsize: raise ex.exceptions.BadIndexAccess( "Accessing - [" + str(idx) + "] > " +\ "heapsize idx " + str(heapsize - 1) ) # check if heap property violated - if it is - fix it if op == 'inc': parent_idx = self.heap.get_parent_idx(idx) cmprator_out = self.heap.cmprator( self.heap.read(idx), self.heap.read(parent_idx) ) while (cmprator_out > 0 and idx >= 0): self.swap_nodes(idx, parent_idx) idx = parent_idx parent_idx = self.heap.get_parent_idx(idx) cmprator_out = self.heap.cmprator( self.heap.read(idx), self.heap.read(parent_idx) ) else: self.heap.max_heapify(idx) self.update_id_idx_map(idx) return True def insert(self, id): """ Insert a new element in the queue """ if id in self.id_to_idx_map: raise ex.exceptions.DupElemInsertion( "Id " + str(id) + " already exists in queue" ) self.heap.inc_heapsize(1) heap_new_idx = self.heap.heapsize - 1 self.heap.write(heap_new_idx, id) self.update_id_idx_map(heap_new_idx) self.update_key(id, self.elem_key_handler(id)) return True def extract_max(self): """ Remove and return elem whose key has max val in queue """ try: max = self.maximum() except ex.exceptions.HeapError as e: raise \ ex.exceptions.HeapError("Cannot extract max - " +\ e.message) self.swap_nodes(0, self.heap.heapsize - 1) self.heap.dec_heapsize(1) self.heap.max_heapify() self.update_id_idx_map() return max def get_iter(self): i = 0 max = self.heap.heapsize while i < max: yield self.heap.read(i) i += 1 def flush(self): count = 0 while self.heap.heapsize > 0: self.extract_max() count += 1 return count
def __init__(self): self.lowers = Heap(is_max=True) # max heap for lower half self.highers = Heap(is_max=False) # min heap for higher half
class Solution(): def __init__(self): self.lowers = Heap(is_max=True) # max heap for lower half self.highers = Heap(is_max=False) # min heap for higher half def get_medians(self, source): medians = [] for item in source: self.add_item(item) self.rebalance() medians.append(self.get_median()) return medians def add_item(self, item): if self.lowers.size() == 0 or item < self.lowers.peek(): self.lowers.add(item) else: self.highers.add(item) def rebalance(self): bigger_heap = self.lowers if self.lowers.size() > self.highers.size( ) else self.highers smaller_heap = self.highers if self.lowers.size() > self.highers.size( ) else self.lowers if bigger_heap.size() - smaller_heap.size() >= 2: smaller_heap.add(bigger_heap.pop()) def get_median(self): bigger_heap = self.lowers if self.lowers.size() > self.highers.size( ) else self.highers smaller_heap = self.highers if self.lowers.size() > self.highers.size( ) else self.lowers if bigger_heap.size() == smaller_heap.size(): return (bigger_heap.peek() + smaller_heap.peek()) / 2 else: return bigger_heap.peek()