【发布时间】:2011-05-23 15:26:09
【问题描述】:
我正在寻找一种更有效的方法来重新排列优先级队列中的项目的优先级。我有一个基于heapq 的(非常天真的)优先级队列实现。相关部分如下:
from heapq import heapify, heappop
class pq(object):
def __init__(self, init= None):
self.inner, self.item_f= [], {}
if not None is init:
self.inner= [[priority, item] for item, priority in enumerate(init)]
heapify(self.inner)
self.item_f= {pi[1]: pi for pi in self.inner}
def top_one(self):
if not len(self.inner): return None
priority, item= heappop(self.inner)
del self.item_f[item]
return item, priority
def re_prioritize(self, items, prioritizer= lambda x: x+ 1):
for item in items:
if not item in self.item_f: continue
entry= self.item_f[item]
entry[0]= prioritizer(entry[0])
heapify(self.inner)
这是一个简单的协程,仅用于演示我的实际应用程序中的重新优先级特征。
def fecther(priorities, prioritizer= lambda x: x+ 1):
q= pq(priorities)
for k in xrange(len(priorities)+ 1):
items= (yield k, q.top_one())
if not None is items:
q.re_prioritize(items, prioritizer)
有测试
if __name__ == '__main__':
def gen_tst(n= 3):
priorities= range(n)
priorities.reverse()
priorities= priorities+ range(n)
def tst():
result, f= range(2* n), fecther(priorities)
k, item_t= f.next()
while not None is item_t:
result[k]= item_t[0]
k, item_t= f.send(range(item_t[0]))
return result
return tst
制作:
In []: gen_tst()()
Out[]: [2, 3, 4, 5, 1, 0]
In []: t= gen_tst(123)
In []: %timeit t()
10 loops, best of 3: 26 ms per loop
现在,我的问题是,在重新确定优先级队列的优先级时,是否存在任何可以避免调用 heapify(.) 的数据结构?我在这里愿意用内存换取速度,但应该可以用纯 Python 实现它(显然比我幼稚的实现要好得多)。
更新:
为了让您了解更多关于特定情况的信息,我们假设在初始(批量)推送之后没有项目被添加到队列中,然后从队列中每次获取(弹出)都会生成大致类似于以下方案的重新优先级数:
- 0*
n,很少 - 0.05*
n,通常 -
n,很少
其中n 是队列中items的当前数量。因此,在任何一轮中,或多或少只有相对较少的项目需要重新确定优先级。所以我希望存在一种能够利用这种模式的数据结构,从而优于在每一轮中强制执行heapify(.) 的成本(以满足堆不变量)。
更新 2:
到目前为止,heapify(.) 方法似乎确实非常有效(相对而言)。我能想到的所有替代方案都需要使用heappush(.),而且它似乎比我最初预期的要贵。 (无论如何,如果问题状态仍然如此,我不得不在python领域之外找到更好的解决方案。
【问题讨论】:
-
这两种优先方案有什么先验知识吗?他们之间有某种关系吗?我不能假设任何事情,那么恐怕您必须致电
heapify(.)才能完成这项工作。 -
@André Caron:实际上可能有几个“优先方案”。但是它们是隐含的(隐藏在数据中),我希望将其保留为“黑匣子”。谢谢
标签: python performance data-structures