我试图在python中实现Uniform-cost search,为此我需要一个优先级队列,我使用标准库中的queue.py。但是,算法结束时会检查队列中是否存在成本较高的路径。如果我的队列中有任何给定值,如果它不可迭代,我如何检查?
由于
答案 0 :(得分:5)
queue.PriorityQueue
实际上是使用list
实现的,put
/ get
方法使用heapq.heappush
/ heapq.heappop
来维护优先级排序在list
内。因此,如果您愿意,您可以迭代内部列表,该列表包含在queue
属性中:
>>> from queue import PriorityQueue
>>> q = PriorityQueue()
>>> q.put((5, "a"))
>>> q.put((3, "b"))
>>> q.put((25, "c"))
>>> q.put((2, "d"))
>>> print(q.queue)
[(2, 'd'), (3, 'b'), (25, 'c'), (5, 'a')]
答案 1 :(得分:3)
PriorityQueue
实现为binary heap,它是在python中使用list
(数组)实现的。要遍历队列,您需要知道有关子列表存储在列表中的位置的规则。
规则是所有节点都有两个子节点,除非它们是拥有子节点的最后一个节点,在这种情况下它们可能有一个子节点。在最后一个节点之后出现的所有节点都有零个孩子(duh)。
节点的子节点与节点在列表中的位置相关。其中i
是列表中节点的索引,那么它的子节点存储在:
2 * i + 1
2 * i + 2
但是,堆的唯一要求是所有节点的子节点的值都大于或等于节点的值(或者大于取决于实现的值)。
例如,在上面关于binrary heap的链接wiki页面中,您将找到以下图像。队列中的第一项是根。非常明显。第二项是根的子项中较大的一项。但是,第三项可以是根节点的剩余节点,也可以是队列中第二个节点的子节点之一。也就是说,队列(25)中的第三项可能与19或1位于同一位置。
因此,要迭代队列,您需要跟踪所有当前“可查看”的节点。例如:
def iter_priority_queue(queue):
if queue.empty():
return
q = queue.queue
next_indices = [0]
while next_indices:
min_index = min(next_indices, key=q.__getitem__)
yield q[min_index]
next_indices.remove(mix_index)
if 2 * min_index + 1 < len(q):
next_indices.append(2 * min_index + 1)
if 2 * min_index + 2 < len(q):
next_indices.append(2 * min_index + 2)
如果您感觉懒惰,可以将方法猴子修补到queue.PriorityQueue
,但我鼓励您使用heapq
模块实现自己的优先级队列类,因为PriorityQueue
来了具有很多过剩功能(主要是线程安全,几乎肯定不需要)。应该注意的是,上述方法不线程安全。如果另一个线程在迭代时修改了队列,那么上面的方法将开始产生错误的数字,如果你很幸运,它可能会产生异常。
答案 2 :(得分:1)
除非您需要queue.queue
提供的线程安全性,因为它主要用作线程安全作业队列而不是通用队列,您可能最好直接使用collections.deque
是可迭代的。