Current section

Files

Jump to
inplace lib adt priority_queue.ex
Raw

lib/adt/priority_queue.ex

defmodule InPlace.PriorityQueue do
alias InPlace.Heap
@doc """
Creates a priority queue.
Currently backed by binary heap.
The priorities are {term(), number()} tuples,
where the 2nd element defines the priority on the 1st element.
Options:
:comparator - the boolean function that compares 2 priorities (default is Kernel.<=/2)
"""
def new(capacity, opts \\ []) do
opts = Keyword.merge(default_opts(), opts)
kv_mapping = init_mapping()
compare_fun = Keyword.get(opts, :comparator)
getter_fun = fn key -> get_mapping(kv_mapping, key) end
heap = Heap.new(capacity,
getter: getter_fun,
comparator: fn key1, key2 -> compare_priorities(getter_fun, key1, key2, compare_fun) end)
%{
mapping: kv_mapping,
heap: heap
}
end
def size(%{heap: heap} = _p_queue) do
Heap.size(heap)
end
def empty?(%{heap: heap} = _p_queue) do
Heap.empty?(heap)
end
def valid?(%{heap: heap} = _p_queue) do
Heap.valid?(heap)
end
def insert(%{mapping: mapping, heap: heap} = _p_queue, key, priority) when is_number(priority) do
key_index = Heap.size(heap) + 1
update_mapping(mapping, key_index, {key, priority})
Heap.insert(heap, key_index)
end
def get_min(%{heap: heap} = _p_queue) do
Heap.get_min(heap)
end
def extract_min(%{mapping: mapping, heap: heap} = _p_queue) do
#extract_mapping(mapping, 1)
min_key = Heap.get_key(heap, 1)
Heap.extract_min(heap)
|> tap(fn _ -> extract_mapping(mapping, min_key) end)
end
defp default_opts() do
Heap.default_opts()
end
defp init_mapping() do
{__MODULE__, make_ref()}
end
defp mapping_key(mapping, key_index) do
{mapping, key_index}
end
defp update_mapping(mapping, key_index, value) do
Process.put(mapping_key(mapping, key_index), value)
end
def get_mapping(mapping, key_index) do
Process.get(mapping_key(mapping, key_index))
end
defp extract_mapping(mapping, key_index) do
Process.delete(mapping_key(mapping, key_index))
end
defp compare_priorities(getter_fun, pkey1, pkey2, compare_fun) do
{_key1, priority1} = getter_fun.(pkey1)
{_key2, priority2} = getter_fun.(pkey2)
compare_fun.(priority1, priority2)
end
end