简体   繁体   English

更改键值的优先级队列

[英]Priority queue with changing values of key

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? 最好的数据结构是什么?

I would recommend one of two approaches: 我建议使用以下两种方法之一:

  1. (Advanced) Use a heap data structure as used by Java's PriorityQueue implementation. (高级)使用Java的PriorityQueue实现所使用的堆数据结构。 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 . 向上筛选和向下筛选是构成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. 这意味着可以在访问时间为O(1)的情况下插入元素,并且调整元素的优先级不会涉及对数据结构的任何操作。 However, the trade-off is that accesssing the highest priority element is O(n). 但是,要权衡的是访问最高优先级元素是O(n)。

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. 您可以采用完全有序的结构,例如平衡的BST ,并在修改树时缓存最小/最大。 [the min is the leftest element, the max is the rightest element]. [最小值是最左边的元素,最大值是最右边的元素]。

This will allow you: 这将使您:
delete,modify,add: O(logn) 删除,修改,添加: O(logn)
findMin/findMax: O(1) findMin / findMax: O(1)

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. 现在,当您想要更改项目的优先级或从优先级队列中删除任意项目时,可以在字典( O(1) )中查找它,以获取其在堆中的位置。 From there, it's an O(log n) operation to move or remove it. 从那里开始,它是一个O(log n)操作来移动或删除它。

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) . 保留“最低节点”指针很容易,并且树上的操作为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) . 我的测试表明,跳过列表优先级队列与基于二进制堆的优先级队列相比具有优势,但是具有一个很大的优势:查找项目是O(log n)而不是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. 我倾向于使用跳过列表,因为它比组合的堆/字典更易于管理,并且比平衡的二叉树性能更好。

If you're just storing numbers as keys, the ArrayList class should work fine. 如果您只是将数字存储为键,则ArrayList类应该可以正常工作。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM