Bucket queue
Bucket queue | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Type | priority queue | |||||||||||||||||||||||
Invented | 1969 | |||||||||||||||||||||||
Invented by | Robert Dial | |||||||||||||||||||||||
|
A bucket queue is a
The bucket queue is the priority-queue analogue of pigeonhole sort (also called bucket sort), a sorting algorithm that places elements into buckets indexed by their priorities and then concatenates the buckets. Using a bucket queue as the priority queue in a selection sort gives a form of the pigeonhole sort algorithm.[2] Bucket queues are also called bucket priority queues[3] or bounded-height priority queues.[1] When used for quantized approximations to real number priorities, they are also called untidy priority queues[4] or pseudo priority queues.[5] They are closely related to the calendar queue, a structure that uses a similar array of buckets for exact prioritization by real numbers.
Applications of the bucket queue include computation of the
Operation
Basic data structure
A bucket queue can handle elements with integer priorities in the range from 0 or 1 up to some known bound C, and operations that insert elements, change the priority of elements, or extract (find and remove) the element that has the minimum (or maximum) priority. It consists of an array A of container data structures; in most sources these containers are doubly linked lists but they could alternatively be dynamic arrays[3] or dynamic sets. The container in the pth array cell A[p] stores the collection of elements whose priority is p.
A bucket queue can handle the following operations:
- To insert an element x with priority p, add x to the container at A[p].
- To change the priority of an element, remove it from the container for its old priority and re-insert it into the container for its new priority.
- To extract an element with the minimum or maximum priority, perform a sequential searchin the array to find the first or last non-empty container, respectively, choose an arbitrary element from this container, and remove it from the container.
In this way, insertions and priority changes take constant time, and extracting the minimum or maximum priority element takes time O(C).[1][6][8]
Optimizations
As an optimization, the data structure can start each sequential search for a non-empty bucket at the most recently-found non-empty bucket instead of at the start of the array. This can be done in either of two different ways, lazy (delaying these sequential searches until they are necessary) or eager (doing the searches ahead of time). The choice of when to do the search affects which of the data structure operations is slowed by these searches. Dial's original version of the structure used a lazy search. This can be done by maintaining an index L that is a
In either of these two variations, each sequential search takes time proportional to the difference between the old and new values of L. This could be significantly faster than the O(C) time bound for the searches in the un-optimized version of the data structure. In many applications of priority queues such as
Another optimization (already given by Dial 1969) can be used to save space when the priorities are monotonic and, throughout the course of an algorithm, always fall within a range of r values rather than extending over the whole range from 0 to C. In this case, one can index the array by the priorities modulo r rather than by their actual values. The search for the minimum priority element should always begin at the previous minimum, to avoid priorities that are higher than the minimum but have lower moduli. In particular, this idea can be applied in Dijkstra's algorithm on graphs whose edge lengths are integers in the range from 1 to r.[8]
Because creating a new bucket queue involves initializing an array of empty buckets, this initialization step takes time proportional to the number of priorities. A variation of the bucket queue described by Donald B. Johnson in 1981 instead stores only the non-empty buckets in a linked list, sorted by their priorities, and uses an auxiliary search tree to quickly find the position in this linked list for any new buckets. It takes time O(log log C) to initialize this variant structure, constant time to find an element with minimum or maximum priority, and time O(log log D) to insert or delete an element, where D is the difference between the nearest smaller and larger priorities to the priority of the inserted or deleted element.[11]
Example
For example, consider a bucket queue with four priorities, the numbers 0, 1, 2, and 3. It consists of an array whose four cells each contain a collection of elements, initially empty. For the purposes of this example, can be written as a bracketed sequence of four sets: . Consider a sequence of operations in which we insert two elements and with the same priority 1, insert a third element with priority 3, change the priority of to 3, and then perform two extractions of the minimum-priority element.
- After inserting with priority 1, .
- After inserting with priority 1, .
- After inserting z with priority 3, .
- Changing the priority of x from 1 to three involves removing it from and adding it to , after which .
- Extracting the minimum-priority element, in the basic version of the bucket queue, searches from the start of to find its first non-empty element: is empty but , a non-empty set. It chooses an arbitrary element of this set (the only element, ) as the minimum-priority element. Removing from the structure leaves .
- The second extract operation, in the basic version of the bucket queue, searches again from the start of the array: , , , non-empty. In the improved variants of the bucket queue, this search starts instead at the last position that was found to be non-empty, . In either case, is found to be the first non-empty set. One of its elements is chosen arbitrarily as the minimum-priority element; for example, might be chosen. This element is removed, leaving .
Applications
Graph degeneracy
A bucket queue can be used to maintain the
Dial's algorithm for shortest paths
In Dijkstra's algorithm for
A variant of the same algorithm can be used for the widest path problem. In combination with methods for quickly partitioning non-integer edge weights into subsets that can be assigned integer priorities, it leads to near-linear-time solutions to the single-source single-destination version of the widest path problem.[16]
Greedy set cover
The
This may be solved using a bucket queue of sets in the input family, prioritized by the number of remaining elements that they cover. Each time that the greedy algorithm chooses a set as part of its output, the newly covered set elements should be subtracted from the priorities of the other sets that cover them; over the course of the algorithm the number of these changes of priorities is just the sum of sizes of the input sets. The priorities are monotonically decreasing integers, upper-bounded by the number of elements to be covered. Each choice of the greedy algorithm involves finding the set with the maximum priority, which can be done by scanning downwards through the buckets of the bucket queue, starting from the most recent previous maximum value. The total time is linear in the input size.[10]
Scheduling
Bucket queues can be used to schedule tasks with deadlines, for instance in packet forwarding for internet data with quality of service guarantees. For this application, the deadlines should be quantized into discrete intervals, and tasks whose deadlines fall into the same interval are considered to be of equivalent priority.[2]
A variation of the quantized bucket queue data structure, the calendar queue, has been applied to scheduling of discrete-event simulations, where the elements in the queue are future events prioritized by the time within the simulation that the events should happen. In this application, the ordering of events is critical, so the priorities cannot be approximated. Therefore, the calendar queue performs searches for the minimum-priority element in a different way than a bucket queue: in the bucket queue, any element of the first non-empty bucket may be returned, but instead the calendar queue searches all the elements in that bucket to determine which of them has the smallest non-quantized priority. To keep these searches fast, this variation attempts to keep the number of buckets proportional to the number of elements, by adjusting the scale of quantization and rebuilding the data structure when it gets out of balance. Calendar queues may be slower than bucket queues in the worst case (when many elements all land in the same smallest bucket) but are fast when elements are uniformly distributed among buckets causing the average bucket size to be constant.[20][21]
Fast marching
In
See also
- Soft heap, a different way of speeding up priority queues by using approximate priorities
References
- ^ ISBN 9780387948607.
- ^ S2CID 5611516
- ^ S2CID 52019258
- ^ MR 2520171
- ^ a b Robledo, Alicia; Guivant, José E. (2010), "Pseudo priority queues for real-time performance on dynamic programming processes applied to path planning" (PDF), in Wyeth, Gordon; Upcroft, Ben (eds.), Australasian Conference on Robotics and Automation
- ^ ISBN 9780080919737. See also p. 157 for the history and naming of this structure.
- ^ S2CID 6754003.
- ^ ISBN 9783540779773.
- ^ MR 1201582
- ^ a b Lim, C. L.; Moffat, Alistair; Wirth, Anthony Ian (2014), "Lazy and eager approaches for the set cover problem", in Thomas, Bruce; Parry, Dave (eds.), Thirty-Seventh Australasian Computer Science Conference, ACSC 2014, Auckland, New Zealand, January 2014, CRPIT, vol. 147, Australian Computer Society, pp. 19–27. See in particular Section 2.4, "Priority Queue", p. 22.
- S2CID 35703411
- S2CID 4417741.
- ISBN 9780120884773.
- ^ ; see in particular Section 8.3.3.6, "Dial's implementation", pp. 194–195.
- ^ Mehlhorn & Sanders (2008) (Exercise 10.11, p. 201) credit this idea to a 1978 paper of E. A. Dinic (Yefim Dinitz).
- MR 0955149
- S2CID 15252482
- MR 0449012
- ISBN 0-262-03384-4
- ^ Brown, R. (October 1988), "Calendar queues: a fast priority queue implementation for the simulation event set problem", S2CID 32086497