修改队列内容后如何从优先级队列中获取最小元素[重复]

Posted

技术标签:

【中文标题】修改队列内容后如何从优先级队列中获取最小元素[重复]【英文标题】:How to get the minimum element from a priority queue after modifying the contents of queue [duplicate] 【发布时间】:2015-06-14 05:25:00 【问题描述】:

我试图在 Java 中使用 priority queue 来实现 Dijkstra 算法。 不幸的是,它返回了错误的结果......我已经找到了问题所在。 这是问题..将节点权重插入队列后,我正在修改这些节点权重,但是当我尝试从优先级队列中删除元素时,它返回历史最小值(插入时的最小值)。@987654322 @不知道优先级队列已被修改..任何帮助将不胜感激...谢谢!

注意:如果需要,我可以添加源代码

【问题讨论】:

PriorityQueue 是一个堆!! 【参考方案1】:

This SO 问题应该对您有所帮助。 Java 中 PriorityQueue 的缺点是,如果插入的元素值发生更改,则不会重新构造优先级队列以反映新顺序。因此,您必须删除并重新插入不断变化的元素以满足您的用例。

【讨论】:

感谢您的帮助!!! 这不是 Java 实现的缺点;任何有效的优先级队列实现都假定队列中的元素在飞行中没有重新加权。这也适用于大多数其他常见的集合(Java 或其他),如哈希图和树。 @dimo414 同意!! :) @dimo414 如果你会看到 c++ priority_queue,你会发现它在更新值时会重新排列,所以这是 Java 的 PriorityQueue 的一个缺点。 更新集合本身会触发重新排序。但是 mutating 集合中的元素不会。 C++ 的实现几乎可以肯定是这样,除非队列比它应有的复杂得多。【参考方案2】:

标准接口不提供更新功能。您已经使用了实现此功能的自定义类型。这是因为,正如标题为“Updating Java PriorityQueue when its elements change priority”的 S.O 帖子中所述:

您必须删除并重新插入,因为队列的工作原理是在插入新元素时将它们放在适当的位置。

S.O 帖子“Java Priority Queue reordering when editing elements”中讨论了这对您的影响:

无论何时添加或删除一个元素,优先级队列都不会处理所有元素......这样做太昂贵了。 PriorityQueue 不提供 api 来通知它有关更改的节点,因为这将要求它提供有效的节点查找,其底层算法不支持。

以上帖子为您实现 Dijsktra 算法提供了替代方法。

如果您有任何问题,请告诉我!

【讨论】:

感谢您的帮助!!! 非常欢迎!!希望你有一个美好的周末!!!! :O)【参考方案3】:

就像Map 的键一样,您放入PriorityQueue 的元素需要是不可变的。将插入PriorityQueue 的元素与PriorityQueue 中的所有现有元素进行比较。因此,如果底层元素发生变化,您的 PriorityQueue 很可能无法保存不变量。

您可以使用的另一种数据结构可以是TreeSetTreeSetremove 运算是 O(lg N)。

【讨论】:

以上是关于修改队列内容后如何从优先级队列中获取最小元素[重复]的主要内容,如果未能解决你的问题,请参考以下文章

数据结构:优先队列-最大最小优先

数据结构——优先队列

优先队列

DelayQueue延迟队列-实现缓存

从队列中获取 O(1) 时间内的最小值/最大值? [关闭]

优先队列与堆