libgraph v0.5.0 PriorityQueue

This module defines a priority queue datastructure, which uses a min heap structure to support pulling the values with the lowest priority out first. This is optimized for use with graph search algorithms where the smallest in/out degree or lowest edge weight/cost should be evaluated before those with higher values. Values with the same priority are dequeued in the order they were originally queued.

This implementation exploits the fact that tuple access times are extremely fast, by storing priorities as buckets of {priority, :queue.t()}, and nesting them such that the lowest priority is always on the left, e.g. {{1, :queue.t()}, {{3, :queue.t()}, nil}}. We use nil to mark that there have been no priorities defined greater than the one on the left, and is where we insert new largest priorities. Inserting a new priority in the middle is just a matter of recursively navigating the heap until we reach the tuple where the left hand is less than the priority we’re inserting, and the right hand is greater, and creating a new nested tuple on the right.

Link to this section Summary

Functions

Create a new priority queue

Pops an element from the queue with the lowest integer value priority

Push a new element into the queue with the given priority

Link to this section Types

Link to this section Functions

Link to this function new()
new() :: t

Create a new priority queue

Link to this function pop(q)
pop(t) :: {:empty, t} | {{:value, term}, t}

Pops an element from the queue with the lowest integer value priority.

Returns {:empty, PriorityQueue.t} if there are no elements left to dequeue.

Returns {{:value, term}, PriorityQueue.t} if the dequeue is successful

This is equivalent to the extract-min operation described in priority queue theory.

Example

iex> pq = PriorityQueue.new
...> pq = Enum.reduce(Enum.shuffle(0..4), pq, fn i, pq -> PriorityQueue.push(pq, ?a+i, i) end)
...> {{:value, ?a}, pq} = PriorityQueue.pop(pq)
...> {{:value, ?b}, pq} = PriorityQueue.pop(pq)
...> {{:value, ?c}, pq} = PriorityQueue.pop(pq)
...> {{:value, ?d}, pq} = PriorityQueue.pop(pq)
...> {{:value, ?e}, pq} = PriorityQueue.pop(pq)
...> {result, _} = PriorityQueue.pop(pq)
...> result
:empty
Link to this function push(q, term, priority)
push(t, term, integer) :: t

Push a new element into the queue with the given priority.

Priorities must be integer values.

Example

iex> pq = PriorityQueue.new
...> pq = PriorityQueue.push(pq, :foo, 1)
...> {result, _} = PriorityQueue.pop(pq)
...> result
{:value, :foo}