更改优先级队列中项目的优先级
使用 Scala 2.9 实现一种 Dijkstra 算法(伪代码)
val queue = new PriorityQueue
queue.insert(...)
while (!queue.isEmpty) {
val u = queue.extractMin
queue.foreach { v =>
if (condition(u, v))
queue.decreaseKey(v, newPriority)
}
}
我想更改 Scala 的 collection.mutable.PriorityQueue
中项目的优先级。
因此尝试
- 删除项目
- 更改优先级
- 重新插入队列。
但我找不到更新优先级或删除特定项目的方法(不是 必须是头元素),如 java.util.PriorityQueue#remove(Object) 所示 从优先级队列中删除项目。
如何使用 scala.collection.mutable.PriorityQueue 完成此任务 或者我必须使用 java.util.PriorityQueue 来代替?
有谁知道缺乏这种方法是否是设计使然,并且会推荐 在更改某些项目的优先级后重建队列(也许可以看看有关 优先级队列的讨论具有动态项目优先级)?
Using Scala 2.9 to implement a kind of Dijkstra algorithm (pseudo code)
val queue = new PriorityQueue
queue.insert(...)
while (!queue.isEmpty) {
val u = queue.extractMin
queue.foreach { v =>
if (condition(u, v))
queue.decreaseKey(v, newPriority)
}
}
I'd like to change priority of an item in Scala's collection.mutable.PriorityQueue
.
Therefore tried to
- remove item
- change priority
- reinsert into queue.
But I can't find a method to either update priority or remove a specific item (not
necessarily head element) like java.util.PriorityQueue#remove(Object)
as apposed in
Removing an item from a priority queue.
How this task can be done with
scala.collection.mutable.PriorityQueue
or do I have to usejava.util.PriorityQueue
instead?Does anyone know whether lack of such a method is by design and it would be recommended
to rebuild the queue after changing priority of some items (maybe take a look at discussion about Priority queue with dynamic item priorities)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
为 PriorityQueue 类型定义一个案例类,与 var 一起使用来表示优先级,这样您就可以找到它并改变优先级。然后 PriorityQueue 就有这个新值。为了获得正确的排序,我必须克隆它,这会重新排序/强制排序。可能有更好的方法来做到这一点,而无需克隆。
Defining a case class for the PriorityQueue type to use with var for priority allows you to find it and mutate the priority. The PriorityQueue then has this new value. To get the ordering correct I had to clone it which reorders/forces the ordering. There might be a better way to do this without cloning.
优先级队列通常使用堆来实现。二叉堆通常使用数组实现,并且如果要删除的元素不在堆的根与其数组排序中最后一个元素之间的路径,则没有明显的方法可以删除它。我认为这就是 Scala 不提供删除任意元素的原因。但是,如果您实现自己的堆,则很容易实现二元(最小)堆的减键:您只需将节点
N
的新优先级与其父级的优先级进行比较,并且如果两者必要交换。重复执行此操作,直到N
位于顶部或N
的父级优先级低于N
本身。Priority queues are commonly implemented with heaps. Binary heaps are commonly implemented using arrays, and if the element you want to remove is not on the path between the root of the heap and its last element in the array ordering, then there is no obvious way to remove it. I assume that this is why Scala doesn't offer removal of arbitrary elements. However, if you implement your own heap, it's easy enough to implement decrease-key for a binary (min-)heap: you just compare the new priority for a node
N
to its parent's priority, and if necessary exchange the two. Do this repeatedly untilN
is at the top orN
's parent has lower priority thanN
itself.我没有使用 Scala 的经验,但我看到的问题是,普通优先级队列对于 Dijkstra 来说是不够的,因为在执行减少键之前,您需要知道特定顶点存储在队列中的位置。换句话说,需要一个字典(哈希表)在预期的恒定时间内将顶点 id 映射到堆内的索引。然后你就得到了减少键的总体 O(log n) 。在我看来,这样的功能不太可能在标准库中找到。不过,从头开始编写一个合适的类应该很容易。
本次讲座解释了这个想法(但在Python中......抱歉)。
I don't have experience with Scala but the problem I see is that a plain priority queue is not enough for Dijkstra since you need to know where a particular vertex is stored in the queue before you can do a decrease-key. In other words, a dictionary (hash table) is required to map vertex ids to indices within the heap in expected constant time. Then you get an overall O(log n) for the decrease-key. It seems unlikely to me that such a functionality can be found in a standard library. Writing a suitable class from scratch should be easy though.
The code at the end of this lecture explains the idea (but in python.. sorry).
不是 Scala 用户,但到目前为止,我从未见过允许 Decrease Key 的内置/预制堆实现,因为 Decrease Key 仅在您可以提供被 DK 的元素(的位置)时才有效。
获得DK操作最简单的方法就是自己实现Heap。我的方法通常是将元素分开(在无组织的数组/向量/链接列表中)并构建指向元素的指针(或数组索引)的堆。然后,给定一个堆节点,您可以通过在数组中访问该元素来查找该元素(取消引用或索引查找)。为了支持 DK 和/或随机删除,您可以向指向堆节点的元素添加一个附加变量(或者保留索引,如果是基于数组的堆)。这允许您在任一方向上进行 O(1) 访问。
如果你的预制堆带有一个接受指向节点的指针的 DK 操作,那么你可以简单地构建一个自制节点对象的堆,它只需将指针包装在一个类中,这样你就可以提供比较运算符(需要建立一个堆)。
Not a Scala user, but so far I've never seen a built-in/pre-made Heap implementation that allows for Decrease Key, because Decrease Key is only effective if you can provide (the location of) the element being DK'd.
The easiest way of getting the DK operation is to implement the Heap yourself. My method is usually to keep my Elements separate (in an unorganized array/vector/linked list) and to build a Heap of pointers-to-Elements (or array-indeces). Then, given a Heap node, you can look up the element by accessing it in the array (dereference or index-lookup). To support DK and/or Random Delete, you can add an additional variable to the Element that points to the Heap node (or keeps the index, if array-based Heap). This allows you to have O(1) access in either direction.
If your pre-made Heap comes with a DK operation that accepts a pointer to the Node, then you can simply build a Heap of self-made Node Objects, which simply wrap the Pointer in a class so you can provide comparison operators (required to build a Heap of them).
我已经实现了一个 类 来完全满足您的需要:
enqueue
dequeue
putValue
I have implemented a class to do exactly what you need:
enqueue
dequeue
putValue