对于列表,heappop将弹出front元素。从列表前面删除元素的时间复杂度为O(n)。 我错过了什么吗?
答案 0 :(得分:5)
heappop()重新排列列表中的log(n)
元素,这样就不必移动每个元素。
这很容易看到:
>>> from random import randrange
>>> from heapq import heapify, heappop
>>> h = [randrange(1000) for i in range(15)]
>>> heapify(h)
>>> h
[80, 126, 248, 336, 335, 413, 595, 405, 470, 592, 540, 566, 484, 970, 963]
>>> heappop(h)
80
>>> h
[126, 335, 248, 336, 540, 413, 595, 405, 470, 592, 963, 566, 484, 970]
>>> # ^----^---------^----^----^----^----^---------^----^----^--- elements that didn't move
请注意,弹出操作没有移动大部分元素(例如248在heappop之前和之后处于相同的位置)。
答案 1 :(得分:1)
堆弹出确实是O(logn)
复杂度。
你缺少的是,来自堆的弹出不,例如“删除第一个元素并将所有元素左移一个”。有一个算法可以在列表中移动元素,弹出后,无法保证列表中的其余元素与之前的顺序相同。
答案 2 :(得分:1)
如果您正在考虑list.pop
做什么,那么文档会有些误导。
如果heap
是minheap,那么heap[0]
确实是最小的项目。 Python的list.pop
方法返回列表的 last 元素,但heapq.heappop
返回堆的最小(第一个!)元素。但是,它通过弹出堆的最后一个元素(这是列表上的O(1)操作),用heap[0]
交换它,冒泡它(这是O(log n)),然后将从heap[0]
中删除的值返回给调用者。
所以:list.pop
返回列表中的最后一项,并且是O(1)
。 heapq.heappop
会向您返回第一个项目,但不会移动整个数组。
答案 3 :(得分:0)
看看heapq.heappop:https://svn.python.org/projects/python/trunk/Lib/heapq.py
的实现它不会从列表的前面删除一个元素,它只返回它并用其他需要O(logn)的元素替换它,并通过删除最后一个元素来减少底层列表的长度。