【问题标题】:Reprioritizing priority queue (efficient manner)重新排列优先级队列(高效方式)
【发布时间】: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


【解决方案1】:

由于新的优先级函数可能与前一个没有关系,因此您必须付出成本才能获得新的排序(并且它至少需要 O(n) 才能找到新排序中的最小元素)。如果您有少量固定数量的优先级函数并在它们之间频繁切换,那么您可以从为每个函数保持一个单独的堆中受益(尽管不使用 heapq,因为它不支持廉价定位和删除对象)堆中间)。

【讨论】:

  • heapq.heapify 是 O(N) 而不是 O(N log N)
  • @John:很好。编辑得当。
  • 现在接受您的回答,因为这让我意识到要击败一个幼稚的 heapify(.) 方法是多么困难。我原来的问题还没有得到妥善解决。谢谢
猜你喜欢
  • 1970-01-01
  • 2014-08-05
  • 2010-10-01
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多