Python,heapq,如何有效修改heapq中的最小元素?

时间:2018-12-08 10:30:40

标签: python data-structures heapq

我正在python 3.7中使用heapq
我有两个关于heapq的问题:

  1. 如果我只想修改min元素,我不知道如何有效地保持堆不变。
    这是我的实现。 (很慢)

    q= [5,8,9,10]
    heapq.heapify(q)
    q[0] = 1200
    heapq.heapify(q)
    
  2. _siftdown()和_siftup()这两个方法有什么用?它们之间有什么区别?如何使用这两种方法来保持堆不变性?

最后,我使用_siftdown()实现代码(但是我仍然对这两种方法感到困惑,并且不能确保我的代码是否正确。

s = time.time()
q = []
for i in range(0, 10000):
    heapq.heappush(q, i)
for i in range(0, 10000):
    q[0] = 10000+i
    heapq._siftup(q,0)
print(q[0])
e2 =time.time()

print(e2-s)

s = time.time()
q = []
for i in range(0, 10000):
    heapq.heappush(q, i)
for i in range(0, 10000):
    q[0] = 10000+i
    heapq.heapify(q)
print(q[0])
e2 =time.time()

print(e2-s)

输出为:

10000
0.09700560569763184
10000
7.193411350250244

1 个答案:

答案 0 :(得分:1)

使用heapq.heapreplace。最小的项始终位于q[0],因此,如有需要,对其进行修改,然后调用:

heapq.heapreplace(q, q[0])

我运行了您的时间并将其改写以提高速度:

import time
import heapq

s = time.time()
q = list(range(0, 10000))
heapq.heapify(q)

for i in range(0, 10000):
    heapq.heapreplace(q, 10000+i)

print(q[0])
e2 = time.time()

print(e2 - s)


s = time.time()
q = list(range(0, 10000))
heapq.heapify(q)

for i in range(0, 10000):
    q[0] = 10000+i
    heapq._siftup(q, 0)

print(q[0])
e2 = time.time()

print(e2 - s)

产生:

10000
0.006845951080322266
10000
0.06091189384460449

创建列表然后调用heapify然后使用heappush更快。

heapq.heapreplaceheapq._siftup快,因为heapreplace使用C模块用于heapq,其中_siftup在Python中。 _siftup_siftdown仅出现在heapq.py中,而不出现在_heapq模块中

请勿致电_siftup_siftdown。它们是heapq的Python实现的内部。

我使用Python 3.2.3对此进行了测试