Priority queue
In computer science, a priority queue is an abstract data type similar to a regular queue or stack abstract data type.
In a priority queue, each element has an associated priority, which determines its order of service. Priority queue serves highest priority items first. Priority values have to be instances of an ordered data type, and higher priority can be given either to the lesser or to the greater values with respect to the given order relation. For example, in Java standard library, PriorityQueue's the least elements with respect to the order have the highest priority. This implementation detail is without much practical significance, since passing to the opposite order relation turns the least values into the greatest, and vice versa.
While priority queues are often implemented using heaps, they are conceptually distinct. A priority queue can be implemented with a heap or with other methods; just as a list can be implemented with a linked list or with an array.
Operations
A priority queue has the following operations:Max-priority queue
-
insert: add an element to setSwith an associated priority. -
maximum: return the element with highest priority. - : This is also known as "
find_max". -
extract_max: remove the element from setSwith highest priority, and return it. - : This is also known as "
delete", or "extract". -
increase_key: increase the associated priority with an element to the new valuek.Min-priority queue
-
insert: add an element to setSwith an associated priority. -
minimum: return the element with lowest priority. - : This is also known as "
find_min". -
extract_min: remove the element from setSwith lowest priority, and return it. - : This is also known as "
delete", or "extract". -
decrease_key: decrease the associated priority with an element to the new valuek.
In some implementations, if two elements have the same priority, they are served in the same order in which they were enqueued. In other implementations, the order of elements with the same priority is undefined.
Implementation
Naive implementations
One can create a simple, but inefficient priority queue in a number of ways. These naive implementations can demonstrate the expected behaviour of a priority queue in a simpler manner.- insert elements into an unsorted array; find and extract element with highest priority
- : Performance: "
insert" performs in constant time, where "extract_max" performs in linear time.
node.element ← element
node.priority ← priority
list.append
extract_max:
highest ← 0
foreach node in list:
if highest.priority < node.priority:
highest ← node
list.remove
return highest.element
- insert elements into a sorted array; extract first element
- : Performance: "
insert" performs in linear time, where "extract_max" performs in constant time.
node.element ← element
node.priority ← priority
for i in :
element ← list.get_at_index
if element.priority < node.priority:
list.insert_at_index
return
extract_max:
highest ← list.get_at_index
list.remove
return highest.element
Usual implementation
To improve performance, priority queues are typically based on a heap, giving performance for inserts and removals, and to build the heap initially from a set of elements. Variants of the basic heap data structure such as pairing heaps or Fibonacci heaps can provide better bounds for some operations.Alternatively, when a self-balancing binary search tree is used, insertion and removal also take time, although building trees from existing sequences of elements takes time; this is typical where one might already have access to these data structures, such as with third-party or standard libraries. From a space-complexity standpoint, using self-balancing binary search tree with linked list takes more storage, since it requires to store extra references to other nodes.
From a computational-complexity standpoint, priority queues are congruent to sorting algorithms. The section on [|the equivalence of priority queues and sorting algorithms], below, describes how efficient sorting algorithms can create efficient priority queues.
Specialized heaps
There are several specialized heap data structures that either supply additional operations or outperform heap-based implementations for specific types of keys, specifically integer keys. Suppose the set of possible keys is.- When only
insert,find-minandextract-minare needed and in case of integer priorities, a bucket queue can be constructed as an array of linked lists plus a pointer, initially. Inserting an item with key appends the item to the 'th list, and updates, both in constant time.extract-mindeletes and returns one item from the list with index, then increments if needed until it again points to a non-empty list; this takes time in the worst case. These queues are useful for sorting the vertices of a graph by their degree. - A van Emde Boas tree supports the
minimum,maximum,insert,delete,search,extract-min,extract-max,predecessorandsuccessor]operations in time, but has a space cost for small queues of about, where is the number of bits in the priority value. The space can be reduced significantly with hashing. - The Fusion tree by Fredman and Willard implements the
minimumoperation in time andinsertandextract-minoperations in time. However it is stated by the author that, "Our algorithms have theoretical interest only; The constant factors involved in the execution times preclude practicality."
extract-min" operation, the time complexity for peek actions can be reduced to in all tree and heap implementations by caching the highest priority element after every insertion and removal. For insertion, this adds at most a constant cost, since the newly inserted element is compared only to the previously cached minimum element. For deletion, this at most adds an additional "peek" cost, which is typically cheaper than the deletion cost, so overall time complexity is not significantly impacted.Monotone priority queues are specialized queues that are optimized for the case where no item is ever inserted that has a lower priority than any item previously extracted. This restriction is met by several practical applications of priority queues.
Summary of running times
Equivalence of priority queues and sorting algorithms
Using a priority queue to sort
The semantics of priority queues naturally suggest a sorting method: insert all the elements to be sorted into a priority queue, and sequentially remove them; they will come out in sorted order. This is actually the procedure used by several sorting algorithms, once the layer of abstraction provided by the priority queue is removed. This sorting method is equivalent to the following sorting algorithms:| Name | Priority Queue Implementation | Best | Average | Worst |
| Heapsort | Heap | |||
| Smoothsort | Leonardo Heap | n | ||
| Selection sort | Unordered Array | |||
| Insertion sort | Ordered Array | |||
| Tree sort | Self-balancing binary search tree |
Using a sorting algorithm to make a priority queue
A sorting algorithm can also be used to implement a priority queue. Specifically, Thorup says:
We present a general deterministic linear space reduction from priority queues to sorting implying that if we can sort up to keys in time per key, then there is a priority queue supportingdeleteandinsertin time andfind-minin constant time.
That is, if there is a sorting algorithm which can sort in time per key, where is some function of and word size, then one can use the given procedure to create a priority queue where pulling the highest-priority element is time, and inserting new elements is time. For example, if one has an sort algorithm, one can create a priority queue with pulling and insertion.
Libraries
A priority queue is often considered to be a "container data structure".The Standard Template Library, and the C++ 1998 standard, specifies as one of the STL container adaptor class templates. However, it does not specify how two elements with same priority should be served, and indeed, common implementations will not return them according to their order in the queue. It implements a max-priority-queue, and has three parameters: a comparison object for sorting such as a function object, the underlying container for storing the data structures, and two iterators to the beginning and end of a sequence. Unlike actual STL containers, it does not allow iteration of its elements. STL also has utility functions for manipulating another random-access container as a binary max-heap. The Boost libraries also have an implementation in the library heap.
Python's module implements a binary min-heap on top of a list.
Java's library contains a class, which implements a min-priority-queue as a binary heap.
.NET's library contains a class, which implements an array-backed, quaternary min-heap.
Scala's library contains a class, which implements a max-priority-queue.
Go's library contains a module, which implements a min-heap on top of any compatible data structure.
Rust's standard library contains a struct, which implements a priority queue with a binary heap.
The Standard PHP Library extension contains the class .
Apple's Core Foundation framework contains a structure, which implements a min-heap.