我需要经常在一个不断更新的集合中找到最小值对象。我需要一个优先级队列类型的功能。这样做的最佳算法或数据结构是什么?我想要有一个排序的树/堆,每次更新对象的值时,我都可以删除该对象,然后将其重新插入树/堆中。有没有更好的方法来实现这一目标?
答案 0 :(得分:1)
为简单起见,二进制堆很难被击败,但它的缺点是 reduce-key 需要O(n)时间。我知道,标准参考文献说它是O(log n),但首先你必须找到该项目。那是标准二进制堆的O(n)。
顺便说一句,如果您决定使用二进制堆,则更改项的优先级不需要删除并重新插入。您可以就地更改项目的优先级,然后将其冒泡或根据需要对其进行筛选。
如果 reduce-key 的性能很重要,那么一个很好的选择是pairing heap,理论上它比Fibonacci堆慢,但更容易实现,在实践中是由于较低的常数因子,比斐波纳契堆更快。在实践中,配对堆与二进制堆相比更有优势,如果你做了很多 reduce-key 操作,它就胜过二进制堆。
您还可以将二进制堆和字典或哈希映射结合起来,并使用堆中项目的位置更新字典。这样可以为更快的 reduce-key 提供更快的内存,并增加其他操作的常数因子。
答案 1 :(得分:0)
引用Wikipedia:
为了提高性能,优先级队列通常使用堆作为它们 主干,为插入和删除提供O(log n)性能,以及 O(n)最初建造。或者,当自平衡二进制时 使用搜索树,插入和删除也需要O(log n)时间, 虽然从现有的元素序列构建树需要O(n 记录时间;这是人们可能已经访问过的典型情况 这些数据结构,例如第三方或标准库。
如果您正在寻找更好的方法,那么优先级队列中的对象必须有一些特殊之处。例如,如果键是从1到10的数字,则基于计数器的方法可能会胜过通常的方法。
答案 2 :(得分:0)
如果您的应用程序看起来像在离散事件模拟中重复选择下一个计划事件,您可能会考虑在例如http://en.wikipedia.org/wiki/Discrete_event_simulation和http://www.acm-sigsim-mskr.org/Courseware/Fujimoto/Slides/FujimotoSlides-03-FutureEventList.pdf。后者总结了该领域不同实现的结果,包括其他评论和答案中考虑的许多选项 - 搜索将在该领域找到大量论文。优先级队列开销确实会使您实时运行仿真的次数有所不同 - 如果您希望模拟需要数周实时的事情,这一点很重要。