为什么heappop时间复杂度在python中是O(logn)(不是O(n))?

时间:2018-02-25 20:57:37

标签: python heap

对于列表,heappop将弹出front元素。从列表前面删除元素的时间复杂度为O(n)。 我错过了什么吗?

4 个答案:

答案 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)的元素替换它,并通过删除最后一个元素来减少底层列表的长度。