java - updatePriority O(log n) 的优先级队列实现
问题描述
我必须实现一个复杂度为 O(log n) 的函数,它更新优先级队列中元素的优先级。这意味着给定一个元素,对其优先级的访问应该是 O(1)。我真的不明白如何做到这一点,如果所有元素都存储在一个堆中,并且它们的位置不断变化,这让我可以 O(n) 搜索堆中的元素。
堆:
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);
}
}
}
}
优先队列:
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) 访问复杂度呢?
解决方案
我可以想到两种方法:
- 您可以添加
Map<V, Integer>
从值映射到索引的 a。这意味着一些额外的簿记,但这还不错,因为当您在主数组中添加或移动元素时,您需要准确地更新它,因此您可以轻松地将其放入setElement
您在操作数组时始终使用的单一方法中。(您甚至可以将数组本身移动到处理它的辅助类中。) - 更新优先级时,不一定需要移除原来的元素;根据您算法的其余部分,只需添加新的并将旧的标记为“已删除”就可以了。(已删除的元素可以定期(摊销的常数时间)或在检测到时从数组中清除。)您可以通过添加
Map<V, Element<K, V>>
从值到当前元素的映射来做到这一点。您可以向您的Element
类添加显式“已删除”标志,或者如果元素的值不再映射到您的Map<V, Element<K, V>>
.
推荐阅读
- html - 样式颜色/日期输入窗口
- sql - 解析函数:ROW_NUMBER( )
- php - 在 CLI 中启用了扩展但在 PHPinfo 中未启用
- javascript - 为什么 Google Hangouts 支持在最新的 Chrome 中不使用 Chrome 扩展程序共享桌面?
- html - 如何使用 django 小部件调整并结合模板类字符串和小部件属性字符串名称
- django - Django内联表单集多个模型
- excel - 如何在excel中减去两个日期和时间字段
- cocoa - 子类化 NSTextStorage 中断列表编辑
- java - UnsatisfiedDependencyException Spring MVC 项目上下文根问题
- kotlin - 用于开放层次结构的 Map 属性委托