在python中从堆中删除任意项

时间:2018-03-05 15:58:38

标签: python data-structures heap binary-heap

是否存在二进制堆实现,我可以在log n time中弹出除root之外的其他元素?

我使用heapq - 但

中的heap.pop( heap.index( wKeys ) )
heapq.heappop(heap)

很慢。我需要一个二进制堆来解决我的问题 - 我有时会使用

{{1}}

但还需要弹出除堆顶部之外的其他元素。所以像heapq imlementation这样的二进制堆应该这样做,但我发现了一个二进制搜索方法。我也看了treap(http://stromberg.dnsalias.org/~strombrg/treap/),也找不到这样的方法。

2 个答案:

答案 0 :(得分:0)

我通过向heappop()heappush()添加参数来修改heapq的实现,这是heapIndex。这需要{item: index}字典,并在弹出或推送heapIndex时更新heap

我还添加了一个新方法heappop_arbitrary(),删除任意元素并更新heapIndex

代码可在此处找到:https://github.com/emoen/heapq_with_index

我已将方法heappop(),heappush()重命名为heappop2(), heappush2(),以避免与原始方法混淆。

我没有为heapq中的任何其他函数实现这个。

答案 1 :(得分:0)

class RemoveHeap:
    def __init__(self):
        self.h = []
        self.track = collections.defaultdict(collections.deque)
        self.counter = itertools.count()

    def insert_item(self, val):
        count = next(self.counter)
        item = [val, count, 'active']
        self.track[val].append(item)
        heapq.heappush(self.h, item)

    def delete_item(self, val):
        if val in self.track:
            items = self.track[val]
            for item in items:
                if item[2] == 'active':
                    item[2] = 'deleted'
                    break

    def pop_item(self):
        while len(self.h) > 0:
            item = heapq.heappop(self.h)
            item_track = self.track[item[0]]
            item_track.popleft()
            if len(item_track) == 0:
                del self.track[item[0]]
            else:
                self.track[item[0]] = item_track
            if item[2] == 'active':
                return item[0]

    def peek_item(self):
        item = self.h[0]
        if item[2] == 'deleted':
            x = self.pop_item()
            self.insert_item(x)
            return x
        return item[0]