键值变化的优先级队列

发布于 2024-12-11 18:41:08 字数 77 浏览 1 评论 0原文

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

I must to simulate a priority queue. Keys in queue are periodically changed. Queue must be able: add element and delete element. What is the best way to do it (with the best complexity)? What is the best data structure?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

意中人 2024-12-18 18:41:08

我推荐以下两种方法之一:

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

I would recommend one of two approaches:

  1. (Advanced) Use a heap data structure as used by Java's PriorityQueue implementation. When an element's priority changes you will need to perform "sift up" and "sift down" operations on the heap to ensure that the top of the heap still represents the highest element in the priority queue. Sift-up and sift-down are operations that form part of heapsort.
  2. (Simple) Use an unordered list as your priority queue. This means that elements can be inserted with O(1) access time and adjusting an element's priority does not involve any manipulation of the data structure. However, the trade-off is that accesssing the highest priority element is O(n).
暖风昔人 2024-12-18 18:41:08

如果您正在寻找一种可以支持任意键不断变化以及任意键的删除/添加的数据结构[任意==不是这个答案中的头部],则常规堆不会解决这个问题,因为它不不能保证快速搜索任意元素,只能搜索到头部。

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

这将使您:

删除、修改、添加:O(logn)

查找最小值/查找最大值:O(1)

If you are looking for a data-structure that can support constant changes in arbitrary keys, and removals/additions of arbitrary keys [arbitrary == not the head in this answer], a regular heap won't do the trick, since it doesn't guarantee quick search for arbitrary elements, only to the head.

You could go for a fully ordered structure, such as a balanced BST, and cache the min/max whenever the tree is modified. [the min is the leftest element, the max is the rightest element].

This will allow you:

delete,modify,add: O(logn)

findMin/findMax: O(1)

寄居人 2024-12-18 18:41:08

总是很难说什么是“最好的”数据结构。一般来说,二叉堆是一个非常好的优先级队列,尽管更改项目的优先级很困难。我过去所做的是创建一个结合字典和堆的数据结构。该字典以项目的标识符为键,并跟踪每个项目在堆中的位置。当在堆中添加、删除或移动项目时,其在字典中的位置会更新。事实证明这很便宜。

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

您还可以使用平衡二叉树作为优先级队列。保留一个“最低节点”指针很容易,并且树上的操作是O(log n)。如果插入和删除相当分散,那么这应该表现得相当好。缺点是实现自平衡二叉树的代码有点复杂。

另一种可能性是为优先级队列使用跳过列表。我的测试表明,跳跃列表优先级队列与基于二进制堆的优先级队列相比毫不逊色,但有一个很大的优势:查找一项的时间复杂度为 O(log n) 而不是 O(n )。跳跃列表的实现并不比二进制堆困难多少。

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

It's always difficult to say what the "best" data structure is. In general, a binary heap makes a very good priority queue, although it is difficult to change an item's priority. What I did in the past is create a data structure that combines a dictionary and a heap. The dictionary is keyed by the item's identifier, and keeps track of each item's location in the heap. When an item is added, removed, or moved in the heap, its location is updated in the dictionary. This turns out to be inexpensive.

Now when you want to change an item's priority or remove an arbitrary item from the priority queue, you can look it up in the dictionary (O(1)) to get its position in the heap. From there, it's an O(log n) operation to move or remove it.

You could also use a balanced binary tree for your priority queue. It's easy enough to keep a "lowest node" pointer, and operations on the tree are O(log n). If insertions and removals are fairly well scattered out, this should perform reasonably well. The drawback is that the code to implement a self-balancing binary tree is a bit involved.

Another possibility is to use a skip list for your priority queue. My tests show that a skip list priority queue compares favorably with a binary heap based priority queue, but has one big advantage: looking up an item is O(log n) rather than O(n). And a skip list isn't much more difficult to implement than a binary heap.

I would tend toward using the skip list because it's easier to manage than the combined heap/dictionary, and it will perform better than the balanced binary tree.

只是我以为 2024-12-18 18:41:08

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

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

If you're just storing numbers as keys, the ArrayList class should work fine.

queue = new ArrayList<int>;
queue.add(27);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文