简体   繁体   English

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

[英]Why heappop time complexity is O(logn) (not O(n)) in python?

For a list, the heappop will pop out the front element. 对于列表,heappop将弹出前面的元素。 Remove an element from the front of a list has time complexity O(n). 从列表前面删除元素的时间复杂度为O(n)。 Do I miss anything? 我想念什么吗?

A heappop() rearranges log(n) elements in the list so that it doesn't have to shift every element. 一个heappop()重新排列列表中的log(n)元素,这样它就不必移动每个元素。

This is easy to see: 这很容易看出:

>>> 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

Note that the popping operation didn't move most of the elements (for example 248 is in the same position before and after the heappop). 请注意,弹出操作没有移动大多数元素(例如248在heappop之前和之后处于相同位置)。

Heap pop is indeed O(logn) complexity. 堆pop确实是O(logn)复杂性。

What you are missing is that pop from a heap is not like "removing the first element and left shift all elements by one". 你所缺少的是从堆中弹出是不是像“除去第一元素和左移一个所有要素”。 There is an algorithm to move element inside the list, after popping, there is no guarantee that the remaining elements in the list are in the same order as before. 有一个算法可以在列表中移动元素,弹出后,无法保证列表中的其余元素与之前的顺序相同。

The documentation is somewhat misleading if you're thinking about what list.pop does. 如果您正在考虑list.pop作用,那么文档会有些误导。

If heap is a minheap, then heap[0] is indeed the smallest item. 如果heap是minheap,那么heap[0]确实是最小的项目。 Python's list.pop method returns the last element of the list, but heapq.heappop returns the smallest (first!) element of the heap. Python的list.pop方法返回列表的最后一个元素,但heapq.heappop返回堆的最小 (第一个!)元素。 However, it does this by popping off the last element of the heap (which is an O(1) operation on a list), swapping it with heap[0] , bubbling it up (this is O(log n)), and then returning the value removed from heap[0] to the caller. 但是,它通过弹出堆的最后一个元素(这是列表上的O(1)操作),使用heap[0]交换它,冒泡它(这是O(log n)),并且然后将从heap[0]删除的值返回给调用者。

So: list.pop returns the last item from a list and is O(1) . 所以: list.pop返回列表中的最后一项,是O(1) heapq.heappop returns the first item to you, but not by shifting the entire array. heapq.heappop返回第一个项目给你,但不是通过移动整个数组。

Take a look at the implementation of heapq.heappop: https://svn.python.org/projects/python/trunk/Lib/heapq.py 看一下heapq.heappop的实现: https ://svn.python.org/projects/python/trunk/Lib/heapq.py

It doesn't remove an element from the front of the list, it just returns it and replaces it with something else which takes O(logn), and reduces the length of the underlying list by removing the last element. 它不会从列表的前面删除一个元素,它只返回它并用其它需要O(logn)的东西替换它,并通过删除最后一个元素来减少底层列表的长度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM