Priority Queues
To use the bindings from this module:
(import :std/misc/pqueue)
make-pqueue
(make-pqueue prio [cmp = <] [capacity = 15]) -> pqueue
prio := function returning priority of elements
cmp := optional heap comparison function, min-heap by default
capacity := optional initial size
Creates a new empty priority queue, a data structure similar to a simple queue, but extended to take the associated priority value of an element into account when pushing, popping and peeking elements.
- prio is a function returning the real priority of an element. It is utilized to determine the insert position whenever some element is about to be pushed onto the priority queue.
- cmp, a comparison function, is used to order the elements based on their
priority, defaulting to
<
. - capacity is the number of elements the pqueue can hold before it needs to resize itself.
Examples:
For example, let's assume we always want to retrieve the longest string
currently within our queue. This could be achieved with string-length
as our
priority function and ordering these lengths via >
:
> (def pq (make-pqueue string-length >))
> (pqueue-push! pq "shortest")
> (pqueue-push! pq "very, very, long")
> (pqueue-push! pq "medium length")
> (pqueue-peek pq)
"very, very, long"
> (pqueue-pop! pq)
"very, very, long"
> (pqueue-peek pq)
"medium length"
pqueue?
(pqueue? pq) -> boolean
pq := priority queue to check
Returns #t
if pq is a priority queue, #f
otherwise.
Examples:
> (let (pq (make-pqueue identity))
(when (pqueue? pq)
(pqueue-push! pq 1000)
(pqueue-push! pq 100)
(pqueue-push! pq 10)
(pqueue-peek pq)))
10
> (import :std/misc/queue)
> (pqueue? (make-queue))
#f
pqueue-size
(pqueue-size pq) -> fixnum
pq := priority queue to inspect
Returns the number of elements queued in pq.
This operation is O(1)
, since priority queues always keep track of their size.
Examples:
> (let (pq (make-pqueue char->integer))
(string-for-each (cut pqueue-push! pq <>) "ABCDEF")
(pqueue-size pq))
6
pqueue-empty?
(pqueue-empty? pq) -> boolean
pq := priority queue to check
Returns #t
if pq has no elements queued, #f
otherwise.
Examples:
> (pqueue-empty? (make-pqueue identity < 1000))
#t
> (make-pqueue identity)
#<pqueue #21>
> (pqueue-push! #21 1)
> (pqueue-push! #21 3)
> (pqueue-push! #21 5)
> (pqueue-empty? #21)
#f
pqueue-push!
(pqueue-push! pq elem) -> unspecified
pq := priority queue to push onto
elem := element to push to pq
Enqueues elem in pq. The insert position depends on the priority and
comparison functions specified in make-pqueue
. Similar to set!
, it's
unspecified what pqueue-push!
returns afterwards.
Examples:
> (defstruct city (name population))
> (def cities [(make-city "Salto" 104028)
(make-city "Санкт-Петербург" 4879566)
(make-city "Qaqortoq" 3089)
(make-city "አዲስ ፡ አበባ" 3352000)
(make-city "Jayapura" 315872)
(make-city "香港" 7448900)])
> (let (pq (make-pqueue city-population))
(for-each (cut pqueue-push! pq <>) cities)
(city-name (pqueue-peek pq)))
"Qaqortoq"
pqueue-pop!
(pqueue-pop! pq [default = absent-obj]) -> any | default | error
pq := priority queue to pop from
default := optional element returned when pq is empty
Pops the next value in pq and returns it. Which element gets popped depends on
the priority and comparison function specified in make-pqueue
. If pq is
empty and a default value is supplied, then default is returned. Otherwise an
error is raised.
Examples:
> (import :std/sugar)
> (let (pq (make-pqueue values))
(for-each (cut pqueue-push! pq <>) [10 1 20 2 30 3])
(until (pqueue-empty? pq)
(displayln (pqueue-pop! pq)))
;; would signal error without default value:
(pqueue-pop! pq 100))
1
2
3
10
20
30
100
pqueue-peek
(pqueue-peek pq) -> any | error
pq := priority queue to peek
Returns the next value in pq without popping it from the priority queue like
pqueue-pop!
does. An error is raised when pq is empty.
Examples:
> (import :std/srfi/1)
> (def pq (make-pqueue length))
> (pqueue-push! pq (iota (random-integer 10)))
> (pqueue-peek pq)
(0 1 2 3 4 5 6 7)
> (pqueue-push! pq [13 21 34 55])
> (pqueue-peek pq)
(13 21 34 55)
pqueue-contents
(pqueue-contents pq) -> list
pq := priority queue of which to extract the contents
Returns the contents of the priority queue as a list, without modifying the priority queue.
Examples:
> (def pq (make-pqueue identity))
> (for-each (cut pqueue-push! pq <>) [8 2 3 4 1 9 7])
> (pqueue-contents pq)
(1 2 3 8 4 9 7)
pqueue
(defsyntax pqueue)
Priority queue type for user-defined generics and destructuring.
Examples:
> (let (pq (make-pqueue string-length >))
(pqueue-push! pq "Mimas")
(pqueue-push! pq "Enceladus")
(pqueue-push! pq "Tethys")
(with ((pqueue internal-heap) pq)
(with ((vector size . vals) internal-heap)
(displayln "size: " size "\nvals: " vals))))
size: 3
vals: ((9 . Enceladus) (5 . Mimas) (6 . Tethys) 0 0 0 0 0 0 0 0 0 0 0 0)