Python的通用优先级队列

Eli*_*sky 45 python queue

我需要在Python代码中使用优先级队列.为了寻找有效的东西,我遇到了堆积.它看起来不错,但似乎只为整数指定.我认为它适用于具有比较运算符的任何对象,但它没有指定它需要哪些比较运算符.

此外,heapq似乎是用Python实现的,所以它并不快.

您是否了解Python中优先级队列的任何快速实现?最理想的情况是,我希望队列是通用的(即适用于具有指定比较运算符的任何对象).

提前致谢

更新:

重新比较heapq,我可以使用(priority, object)查理马丁建议的,或者只是__cmp__为我的对象实现.

我还在寻找比他更快的东西heapq.

Cha*_*tin 39

嗯,Queue.PriorityQueue?回想一下,Python不是强类型的,所以你可以保存你喜欢的任何东西:只需要创建(优先级,事物)元组,然后设置它.

  • @larsmans我在Python2.6中做了一些简单的测试,表明`heapq`大约是`PriorityQueue`的两倍. (14认同)
  • Queue.PriorityQueue已同步.对于不需要同步的情况,会产生不必要的开销. (5认同)
  • 没有偷看功能:-( (2认同)
  • @Eli Bendersky:你在这和`heapq`之间进行了性能比较吗?我认为`heapq`更快,因为它没有做任何锁定. (2认同)
  • Python 是强类型的。它不是静态的,明显的类型。 (2认同)

Eli*_*sky 18

我最终实现了一个包装器heapq,添加了一个用于维护队列元素唯一的dict.结果应该对所有运营商都非常有效:

class PriorityQueueSet(object):

    """
    Combined priority queue and set data structure.

    Acts like a priority queue, except that its items are guaranteed to be
    unique. Provides O(1) membership test, O(log N) insertion and O(log N)
    removal of the smallest item.

    Important: the items of this data structure must be both comparable and
    hashable (i.e. must implement __cmp__ and __hash__). This is true of
    Python's built-in objects, but you should implement those methods if you
    want to use the data structure for custom objects.
    """

    def __init__(self, items=[]):
        """
        Create a new PriorityQueueSet.

        Arguments:
            items (list): An initial item list - it can be unsorted and
                non-unique. The data structure will be created in O(N).
        """
        self.set = dict((item, True) for item in items)
        self.heap = self.set.keys()
        heapq.heapify(self.heap)

    def has_item(self, item):
        """Check if ``item`` exists in the queue."""
        return item in self.set

    def pop_smallest(self):
        """Remove and return the smallest item from the queue."""
        smallest = heapq.heappop(self.heap)
        del self.set[smallest]
        return smallest

    def add(self, item):
        """Add ``item`` to the queue if doesn't already exist."""
        if item not in self.set:
            self.set[item] = True
            heapq.heappush(self.heap, item)
Run Code Online (Sandbox Code Playgroud)

  • 看起来不错,但你应该使用"set in set"而不是"set.has_key(item)".它更快(减少方法调用开销),第二个已在Python 3.0中删除. (3认同)
  • `items = []`是一个坏主意,因为列表是可变的.另外,你可以在`__init __()`中做`self.set = set(items)`. (2认同)
  • @alecxe我认为这是因为它不支持`decrease-key`,而`decrease-key`是这些文档中整个“已删除”概念的原因(正是“已删除”逻辑使函数看起来更少干净的) (2认同)

Guy*_*y s 11

当使用优先级队列时,reduce-key是许多算法必须具备的操作(Dijkstra算法,A*,OPTICS),我想知道为什么Python的内置优先级队列不支持它.其他答案都没有提供支持此功能的解决方案.

同时也支持减少按键操作的优先级队列为这个由丹尼尔Stutzbach实现完美的工作对我来说与Python 3.5.

from heapdict import heapdict

hd = heapdict()
hd["two"] = 2
hd["one"] = 1
obj = hd.popitem()
print("object:",obj[0])
print("priority:",obj[1])

# object: one
# priority: 1
Run Code Online (Sandbox Code Playgroud)

  • 似乎是一个合理的答案:downvoters应该在这里解释一下. (2认同)

小智 8

您可以将heapq用于非整数元素(元组)

from heapq import *

heap = []
data = [(10,"ten"), (3,"three"), (5,"five"), (7,"seven"), (9, "nine"), (2,"two")]
for item in data:
    heappush(heap, item)
sorted = []
while heap:
    sorted.append(heappop(heap))
print sorted
data.sort()
print data == sorted
Run Code Online (Sandbox Code Playgroud)


Kiv*_*Kiv 7

我没用过它,但你可以试试PyHeap.它是用C语言写的,所以希望它对你来说足够快.

你是积极的heapq/PriorityQueue会不够快?它可能值得与其中一个开始,然后分析,看看它是否真的是你的性能瓶颈.


Har*_*lby 6

您是否查看了heapq页面上的"Show Source"链接?有一个例子比使用带有(int,char)元组列表的堆作为优先级队列的不到一半.

  • 我的立场得到了纠正(本杰明彼得森).heapq使用C实现,这很快. (5认同)