具有更改键值的优先级队列

时间:2011-10-26 15:30:46

标签: java c++ algorithm data-structures

我必须模拟优先级队列。队列中的密钥会定期更改。队列必须能够:添加元素和删除元素。最好的方法是什么(具有最佳复杂性)?什么是最好的数据结构?

4 个答案:

答案 0 :(得分:2)

我建议采用以下两种方法之一:

  1. (高级)使用Java的PriorityQueue实现使用的堆数据结构。当元素的优先级发生变化时,您需要在堆上执行“筛选”和“筛选”操作,以确保堆顶部仍然代表优先级队列中的最高元素。筛选和筛选是构成heapsort的一部分的操作。
  2. (简单)使用无序列表作为优先级队列。这意味着可以使用O(1)访问时间插入元素,并且调整元素的优先级不涉及对数据结构的任何操作。然而,权衡是访问最高优先级元素是O(n)。

答案 1 :(得分:1)

如果您正在寻找一种数据结构,可以支持任意键的持续更改,以及任意键的删除/添加[任意==不是本答案中的头部],那么常规堆将无法解决问题,因为它不能保证快速搜索任意元素,只能到头部。

您可以使用完全有序的结构,例如balanced BST,并在修改树时缓存最小值/最大值。 [min是leftest元素,max是最正确的元素]。

这将允许您:
删除,修改,添加:O(logn)
findMin / findMax:O(1)

答案 2 :(得分:1)

总是很难说出“最佳”数据结构是什么。通常,二进制堆会产生一个非常好的优先级队列,尽管很难更改项目的优先级。我过去所做的是创建一个结合了字典和堆的数据结构。字典由项目的标识符键控,并跟踪每个项目在堆中的位置。在堆中添加,删除或移动项目时,其位置将在字典中更新。结果证明是便宜的。

现在,当您想要更改项目的优先级或从优先级队列中删除任意项目时,您可以在字典(O(1))中查找它以获得它在堆中的位置。从那里开始,移动或移除它是O(log n)操作。

您还可以使用平衡二叉树作为优先级队列。保持“最低节点”指针很容易,树上的操作是O(log n)。如果插入和移除相当分散,这应该相当好。缺点是实现自平衡二叉树的代码有点涉及。

另一种可能性是使用skip list作为优先级队列。我的测试显示跳过列表优先级队列优先于基于二进制堆的优先级队列,但有一个很大的优点:查找项目是O(log n)而不是O(n)。跳过列表并不比二进制堆更难实现。

我倾向于使用跳过列表,因为它比组合堆/字典更容易管理,并且它的性能优于平衡二叉树。

答案 3 :(得分:0)

如果您只是将数字存储为键,则ArrayList类应该可以正常工作。

queue = new ArrayList<int>;
queue.add(27);