来自Python docs:
后两个函数[heapq.nlargest和heapq.nsmallest]对较小的n值表现最佳。对于 值越大,使用sorted()函数效率越高。 此外,当n == 1时,使用内置的min()和更高效 max()函数。
如果我想检索最小堆中的最小元素,为什么Python文档建议使用min()
,我假设在O(n)时间内运行,
我可以在O(1)时间内检索堆中的第一个元素吗? (我假设堆中的第一个元素是最小的)
答案 0 :(得分:2)
nsmallest
提供的nlargest
和heapq
方法并不假设传递给它们的参数已经是堆格式。相反,他们试图在论证遍历时“堆积”论证,这比对小k值的前k元素进行彻底排序更有效,但是对于k恰好等于1,它甚至更快地避免支付随你堆积开销,只需直接使用min
。
你的陈述是正确的。如果给你一个你可以保证已经堆积的数组,并且之后没有改变,那么访问第一个元素会给你min(分别是max-heap的最大值)。
看source code for heapq(也许我正在看旧代码?)对我来说似乎仍然很奇怪。 nsmallest
有n ==1
这样的特殊情况(第397行):
def nsmallest(n, iterable, key=None):
"""Find the n smallest elements in a dataset.
Equivalent to: sorted(iterable, key=key)[:n]
"""
# Short-cut for n==1 is to use min() when len(iterable)>0
if n == 1:
it = iter(iterable)
head = list(islice(it, 1))
if not head:
return []
if key is None:
return [min(chain(head, it))]
return [min(chain(head, it), key=key)]
# ... rest of function
只是在解释器中使用该表达式使它看起来很奇怪:
In [203]: foo = list(itertools.islice([1,2,3], 1)); it = iter([1,2,3]); x = itertools.chain(foo, it);
In [204]: x.next()
Out[204]: 1
In [205]: x.next()
Out[205]: 1
In [206]: x.next()
Out[206]: 2
In [207]: x.next()
Out[207]: 3
In [208]: x.next()
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-208-e05f366da090> in <module>()
----> 1 x.next()
StopIteration:
它似乎正在构建一个生成器(它立即变为list
)只接受第一个元素(正如你可能期望的最小堆),但奇怪的是chain
s它有一个普通的旧发电机,它将遍及整个阵列。
我同意,如果您从list
开始并想要查询最小元素,最好将其保留为list
并使用min
。但是,如果你被交给最小堆,是的,你应该只检查第一个元素 - 这是首先将它堆积起来的一部分。
但无论如何,这个源代码对于将最小堆传递给min
看起来很奇怪 - 我非常欢迎更多关于它正在做什么的解释 - 并且可能指向一些更近期的C级代码heapq的实现,如果有的话。
答案 1 :(得分:0)
如果您只需要在堆化列表中选择一个最小元素,只需执行 list[0]:
import heapq
lst = [1,-1,100,200]
heapq.heapify(lst)
min_value = lst[0]
上面的文档是指获取 n 个最小的数字,如果 n 很大,堆不是最有效的数据结构。