【问题标题】:How can I trigger heapification of a PriorityQueue?如何触发 PriorityQueue 的堆积?
【发布时间】:2013-10-04 19:46:42
【问题描述】:

我将以下代码用于PriorityQueue<Node<T>>,其中Node<T> 不是Comparable

final Map<Node<T>, Double> distances = new HashMap<>();

PriorityQueue<Node<T>> queue = new PriorityQueue<Node<T>>(graph
        .getNodes().size(), new Comparator<Node<T>>() {
    @Override
    public int compare(Node<T> o1, Node<T> o2) {
        return distances.get(o1).compareTo(distances.get(o2));
    }
});

稍后在我的代码中,我使用distances.put(...) 修改了地图中节点的距离。如何确保正确更新优先级队列以反映新的排序顺序?

我查看了PriorityQueuesource 并看到它的peekpollelement 方法都只是得到queue[0],但我不知道如何更新队列的顺序,因为内部方法heapifyprivate

【问题讨论】:

标签: java data-structures priority-queue


【解决方案1】:
if(!priorityQueue.isEmpty()) {
    priorityQueue.add(priorityQueue.remove());
}

应该是触发重新堆化的简单方法。 如所见here

【讨论】:

    【解决方案2】:

    据我所知,您不能使用默认实现。但是,您可以解决它。这取决于您使用优先级队列的目的:

    1. 仅在节点优先级增加时更新
    2. 用于在节点的优先级增加和减少时进行更新

    案例 1 是一个更简单的案例,因为 PriorityQueue 已经为您维护了优先级顺序。只需将具有较高优先级的节点添加到队列中,并跟踪之前是否已从优先级队列中弹出节点。 (使用布尔数组或哈希表)

    当你弹出一个节点时,如果它之前没有被弹出过,你可以保证它是队列中优先级最低的那个,即使你之前已经在队列中添加了多个副本。

    情况 2 比较棘手,需要在每个节点中使用一个布尔变量来跟踪它是否“启用”。此外,您需要一个哈希表或数组,以便您可以访问优先级队列中的节点。当您想更新节点的优先级时,您必须在添加新节点时“禁用”队列中的现有节点。还要跟踪您刚刚添加为“新”现有节点的节点。弹出时,只需忽略“禁用”的节点即可。

    至于时间复杂度,添加的摊余成本仍然是 O(log n)。这是因为在“heapify”中更新一个节点在堆中的位置的成本是 O(log n),它渐近地等于调用 offer。弹出的时间成本将根据添加重复节点与有效节点的比例而增加。

    或者,编写您自己的更新优先级队列。

    【讨论】:

      猜你喜欢
      • 2010-10-17
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      • 2020-01-19
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 2015-09-01
      相关资源
      最近更新 更多