简体   繁体   中英

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. 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).

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)

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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