使用updatePriority O(log n)实现优先级队列

时间:2018-05-17 16:58:24

标签: java algorithm data-structures heap priority-queue

我必须实现复杂度为O(log n)的函数,该函数更新优先级队列中元素的优先级。这意味着给定一个元素,对其优先级的访问应该是O(1)。我真的不明白如何做到这一点,如果所有元素都存储在堆中,并且它们的位置不断变化,这使我可以在堆中搜索元素。

堆:

public class Heap<K, V> {
  private int size;
  private Element<K, V> heap[];
  private Comparator<? super K>  comparator;

  public Heap(Comparator<? super K>  comparator) {
  //
  }

  //
  public void add(K priority, V value) {
    int i;

    size++;
    if(size > heap.size()) resize();

    i = size;
    heap[i] = new Element(priority, value);

    while(i > 0 || comparator.compare(heap[parent(i)].priority, heap[i].priority) < 0) {
      swap(i, parent(i));
    }
  }

  // O(log n)
  public void updatePriority(int i, K priority) {
    K oldPriority = heap[i].priority;
    heap[i] = new Element(priority, heap[i].value);

    if(comparator.compare(oldPriority, heap[i].priority) > 0) {
      heapify(i);
    } else {
      while(i > 0 && comparator.compare(heap[parent(i)].priority, heap[i].priority)) < 0) {
        swap(i, parent(i));
        i = parent(i);
      } 
    }
  }
 }

的PriorityQueue:

public class PriorityQueue<K, V> {

  private Heap<Element<K, V>> heap;
  private Comparator<? super K>  comparator;

  public PriorityQueue(Comparator<? super K>  comparator) {
    heap = new Heap<K, V>(comparator);
  }

  //

  // Should be O(log n)
  public void updatePriority(K priority, V elem) {
    // get index of elem in O(1)
    heap.updatePriority(indexOfElem, priority);
  }
}

元素:

public class Element<K, V> {
  public K priority;
  public V value;

  public Element(K priority, V value) {
    this.priority = priority;
    this.value = value;
  }
}

此优先级队列应该用于实现Prim的算法。那么我该怎样才能获得O(1)访问复杂性?

2 个答案:

答案 0 :(得分:0)

我可以想到两种方法:

  1. 您可以添加从值映射到索引的Map<V, Integer>。这意味着一些额外的簿记,但它不会坏,因为您需要在主阵列中添加或移动元素时完全更新它,这样您就可以轻松地将其放入操作数组时总是使用的单setElement方法。 (你甚至可以将数组本身移动到一个处理它的辅助类中。)
  2. 更新优先级时,您不一定需要删除原始元素;根据你的算法的其余部分,简单地添加新的算法并将旧的标记为&#34;删除&#34;可能是好的。 (已删除的元素可以定期(在分摊 - 常量时间)或检测到时从阵列中清除。)您可以通过从值添加Map<V, Element<K, V>>映射到当前元素来执行此操作。你可以添加一个明确的&#34;删除&#34;如果某个元素的值不再映射到Element,则只需将该元素计为已删除的Map<V, Element<K, V>>

答案 1 :(得分:0)

您的add方法存在错误。这一行:

while(i > 0 || comparator.compare(heap[parent(i)].priority, heap[i].priority) < 0) {

||应为&&