你如何创建一个在O(n)时间运行的堆迭代器?

时间:2018-03-14 17:56:53

标签: python heap

def __iter__(self):
    try:
        while True:
            yield self.extract()
    except IndexError:
        return
    return iter([])

这就是我目前正在尝试做的事情。我们的想法是枚举堆中的所有项目,并且必须在O(n)时间内运行。 上面提到的提取函数从堆中删除了最高优先级的项目。

这是实施的其余部分:

from copy import copy 
class Heap:
    """
    A heap-based priority queue
    Items in the queue are ordered according to a comparison function
    """

    def __init__(self, comp):
        """
        Constructor
        :param comp: A comparison function determining the priority of the included elements
        """
        self.comp = comp
        self.heap = []
        self.size = len(self.heap)

    def __len__(self):
        return len(self.heap)

    def peek(self):
        if self.__len__() == 0:
            raise IndexError
        else:
            return self.heap[0]

    def insert(self, item):
        pass

    def _siftdown(self, startpos, pos):
        newitem = self.heap[pos]
        # Follow the path to the root, moving parents down until finding a place
        # newitem fits.
        while pos > startpos:
            parentpos = (pos - 1) >> 1
            parent = self.heap[parentpos]
            if newitem < parent:
                self.heap[pos] = parent
                pos = parentpos
                continue
            break
        self.heap[pos] = newitem

    def siftup(self, pos):
        endpos = len(self.heap)
        startpos = pos
        newitem = self.heap[pos]
        # Bubble up the smaller child until hitting a leaf.
        childpos = 2*pos + 1    # leftmost child position
        while childpos < endpos:
            # Set childpos to index of smaller child.
            rightpos = childpos + 1
            if rightpos < endpos and not self.heap[childpos] < self.heap[rightpos]:
                childpos = rightpos
                # Move the smaller child up.
                self.heap[pos] = self.heap[childpos]
                pos = childpos
                childpos = 2*pos + 1
        # The leaf at pos is empty now.  Put newitem there, and bubble it up
        # to its final resting place (by sifting its parents down).
        self.heap[pos] = newitem
        self.siftdown(self.heap, startpos, pos)

    def heapify(self,heap,i):
        l = (2*i) + 1
        r = (2*i) + 2 
        if l < len(heap) and heap[l] < heap[i]:
            small = l 
        else:
            small = i
        if r < len(heap) and heap[r] < heap[small]:
            small = r

        if small != i:
            heap[i], heap[small] = heap[small], heap[i]
            self.heapify(heap,small)

    def extract(self):
        if self.is_empty():
            raise IndexError
        minimum = self.heap[0]
        self.heap[0] = self.heap[-1] 
        self.size -= 1 
        self.heapify(self.heap,0)
        return minimum

    def extend(self, seq):
        pass

    def clear(self):
        pass

    def __iter__(self):
        try:
            while True:
                yield self.extract()
        except IndexError:
            return
        return iter([])


    def is_empty(self):
        """
        Checks if this heap is empty
        :return: True if the heap is empty
        """
        return len(self.heap) == 0

    def __bool__(self):
        """
        Checks if this heap contains items
        :return: True if the heap is non-empty
        """
        return not self.is_empty()

    def __repr__(self):
        """
        A string representation of this heap
        :return:
        """
        return 'Heap([{0}])'.format(','.join(str(item) for item in self))


def find_median(seq):
    """
    Finds the median (middle) item of the given sequence.
    Ties are broken arbitrarily.
    :param seq: an iterable sequence
    :return: the median element
    """
    if not seq:
        raise IndexError
    min_heap = Heap(lambda a, b: a <= b)
    max_heap = Heap(lambda a, b: a >= b)
    raise IndexError

0 个答案:

没有答案