简体   繁体   中英

Structure like priority queue but with something like lower bound

I want a structure to store (for example) numbers where I can insert and remove elements, my structure remains sorted always (like a priority queue) BUT with the possibility of knowing where is a given number, and every operation in logarithmic time.

Maybe with lower_bound, upper_bound, or just a binary search, but in priority_queue what blocks me to do binary search is that I cannot access the elements with an index, only the first one.

A priority queue does not keep things in sorted order. At least, not typically. A priority queue makes it possible for you to quickly obtain the next item in the sequence. But you can't efficiently access, say, the 5th item in the queue.

I know of three different ways to build a priority queue in which you can efficiently access items by key:

  • Use a balanced binary search tree to implement the queue. Although all operations are O(log n), typical running time is slower than a binary heap.
  • Implement the heap priority queue as a skip list . This is a good option. I've seen some people report that a skip list priority queue outperforms a binary heap. A search for [C++ skip list] will return you lots of implementations.
  • What I call an indexed binary heap also works. Basically, you marry a hash map or dictionary with a binary heap. The map is indexed by key, and its value contains the index of the item in the heap array. Such a thing is not difficult to build, and is quite effective.
  • Come to think of it, you can make an indexed version of any type of heap.

You have a number of options. I rather like the skip list, myself, but your mileage may vary.

The indexed binary heap, as I pointed out, is a hybrid data structure that maintains a dictionary (hash map) and a binary heap. Briefly how it works:

The dictionary key is the field that you use to look up an item that you put into the heap. The value is an integer: the index of that item in the heap.

The heap itself is a standard binary heap implemented in an array. The only difference is that every time you move an item from one place to another in the heap, you update its location in the dictionary. So, for example, if you swap two items, you have to swap not only the items themselves in the array, but also their positions as stored in the dictionary. For example:

heap is an array of string references
dict is a dictionary, keyed by string

swap (a, b)
{
    // swap item at heap[a] with item at heap[b]
    temp = heap[a]
    heap[a] = heap[b]
    heap[b] = temp
    // update their positions in the dictionary
    dict[heap[a]] = b
    dict[heap[b]] = a
}

It's a pretty simple modification of a standard binary heap implementation. You just have to be careful to update the position every time you move an item.

You can also do this with node-based heaps like Pairing heap, Fibonacci heap, Skew heap, etc.

I think you're looking for an order statistics tree , an augmented BST that supports all the regular BST operations in time O(log n), along with two others:

  • rank(elem): return which index elem would occupy in the sorted sequence.
  • index(k): given an index k, return the element at that index in the sorted sequence.

The two above operations run in O(log n) time, making them extremely fast.

You can treat an order statistics tree as a priority queue. Insertions work as normal BST insertions, and to extract the lowest/highest element you just remove the smallest/greatest element from the tree, which you can do in time O(log n) by just walking down the left or right spines of the tree.

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