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

Priority queue with changing values of key

本文关键字:优先级 队列 键值      更新时间:2023-10-16

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

我推荐以下两种方法:

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

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

你可以选择一个完全有序的结构,比如平衡的BST,当树被修改时缓存最小/最大值。[最小值是最左边的元素,最大值是最右边的元素]。

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

很难说什么是"最佳"数据结构。一般来说,二进制堆是一个非常好的优先级队列,尽管很难更改项的优先级。我过去所做的是创建一个数据结构,它结合了字典和堆。字典以项的标识符作为键,并跟踪每个项在堆中的位置。当在堆中添加、删除或移动一个项时,它在字典中的位置将被更新。这是很便宜的。

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

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

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

我倾向于使用跳跃表,因为它比组合堆/字典更容易管理,并且它将比平衡二叉树执行得更好。

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

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