Exemplo n.º 1
0
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()
Exemplo n.º 2
0
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
Exemplo n.º 3
0
 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
     )
Exemplo n.º 4
0
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
Exemplo n.º 5
0
 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
Exemplo n.º 6
0
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()