更新元素后重新堆化 java.util.PriorityQueue

Posted

技术标签:

【中文标题】更新元素后重新堆化 java.util.PriorityQueue【英文标题】:Reheapify java.util.PriorityQueue after updating elements 【发布时间】:2011-12-29 03:11:01 【问题描述】:

我有一个包含对某些对象的引用的 PriorityQueue。当我最初将元素插入优先级队列时,排序由数据结构维护。现在,在删除操作之后,我更新了一些由优先级队列持有的引用。理想情况下,这需要对优先级队列进行 reheapify 操作,但很明显,因为我在外部修改选定的引用,所以无法触发 reheapify。那么,在对队列中的任意元素进行修改的情况下,确保我能够获得像 fast extract max 这样的堆优势的最佳方法是什么?我知道我需要更好的数据结构?

更具体地说,我需要在 Java 中实现类似斐波那契堆的东西。 http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm 可以吗?

【问题讨论】:

如果您有兴趣,我有一个 Java 斐波那契堆的实现。可通过keithschwarz.com/interesting/code/?dir=fibonacci-heap 在线获取。希望对您有所帮助! 即使斐波那契堆在面对元素权重的带外变化时也没有弹性。我认为您需要先删除一个元素,然后再对其进行修改并重新插入。 我猜从堆中删除任意元素需要 O(n) 堆构造。 我猜的问题是 PriorityQueue 为我提供了线性时间删除操作。如果数据结构足够透明,我可以在外部维护优先级队列中所有元素的索引,这样我就可以在 O(lg V) 时间内实现 DECREASE-KEY 操作。有没有人看到任何其他可以帮助我实现这一目标的数据结构? 另见***.com/questions/1871253/… 【参考方案1】:

您可以使用自己的树来允许重复元素而不是堆。 不过更简单的是,您可以使用TreeMap<PriorityKey, LinkedHashSet<Value>>。 所有操作都是O(log priorityType):

添加是get(priority).add(value),如果get返回null,put(priority, new LinkedHashSet()) 删除任意元素是类似的,只是如果 Set 为空则需要从映射中删除优先级。 poll() 是

--

Entry<PriorityKey, LinkedHashSet<Value>> e = map.firstEntry(); 
if (e==null) return null; 
Iterator<Value> i = e.getValue().iterator(); 
Value v = i.next(); //must always have at least one element.
i.remove(); 
if (!i.hasNext()) map.remove(e.getKey());
return v;

如果您需要更改优先级,您必须删除和添加元素。

【讨论】:

OK ...所以我想说Java中的PriorityQueue既没有实现DecreaseKey操作,也没有为用户提供有效实现它的方法。 @iamrohitbanga,在堆中找到一个键是 O(n),然后你可以删除/添加它是 (log N),如果你需要访问队列中的随机元素,你会有树会更好。【参考方案2】:

也许 NavigableMap 会满足您的需求:轻松识别“最高”或“最低”元素、快速插入和访问时间,并且您可以轻松更新值。

http://docs.oracle.com/javase/7/docs/api/java/util/NavigableMap.html

TreeMap 实现了 NavigableMap,因此提供了 firstEntry/lastEntry 方法等等。

【讨论】:

地图中不能有重复的元素,并且必须按优先级排序。使用树(映射)的解决方案涉及映射优先级->集合。 (我发布的)

以上是关于更新元素后重新堆化 java.util.PriorityQueue的主要内容,如果未能解决你的问题,请参考以下文章

堆排序

堆排序和计数排序

西装外套 |炽热 | RadioGroup \ Radio:更新数据上下文后重新渲染页面元素

Ajax 更新后在 jQuery 中重新绑定事件(更新面板)

Ajax 更新后在 jQuery 中重新绑定事件(更新面板)

数组堆化