Current section
Files
Jump to
Current section
Files
src/gleamy@leftist_heap.erl
-module(gleamy@leftist_heap).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([new/1, find_min/1, insert/2, delete_min/1, merge/2]).
-export_type([tree/1, heap/1]).
-type tree(FLP) :: empty | {tree, integer(), FLP, tree(FLP), tree(FLP)}.
-opaque heap(FLQ) :: {heap, tree(FLQ), fun((FLQ, FLQ) -> gleam@order:order())}.
-spec new(fun((FLR, FLR) -> gleam@order:order())) -> heap(FLR).
new(Compare) ->
{heap, empty, Compare}.
-spec find_min(heap(FLW)) -> {ok, FLW} | {error, nil}.
find_min(Heap) ->
case erlang:element(2, Heap) of
{tree, _, X, _, _} ->
{ok, X};
empty ->
{error, nil}
end.
-spec make(FNH, tree(FNH), tree(FNH)) -> tree(FNH).
make(X, A, B) ->
Rank_a = case A of
{tree, R, _, _, _} ->
R;
empty ->
0
end,
Rank_b = case B of
{tree, R@1, _, _, _} ->
R@1;
empty ->
0
end,
case Rank_a < Rank_b of
true ->
{tree, Rank_a + 1, X, B, A};
_ ->
{tree, Rank_b + 1, X, A, B}
end.
-spec merge_trees(tree(FMJ), tree(FMJ), fun((FMJ, FMJ) -> gleam@order:order())) -> tree(FMJ).
merge_trees(H1, H2, Compare) ->
case {H1, H2} of
{H, empty} ->
H;
{empty, H@1} ->
H@1;
{{tree, _, X, A1, B1}, {tree, _, Y, A2, B2}} ->
case Compare(X, Y) of
gt ->
make(Y, A2, merge_trees(H1, B2, Compare));
_ ->
make(X, A1, merge_trees(B1, H2, Compare))
end
end.
-spec insert(heap(FLT), FLT) -> heap(FLT).
insert(Heap, Item) ->
{heap,
merge_trees(
{tree, 1, Item, empty, empty},
erlang:element(2, Heap),
erlang:element(3, Heap)
),
erlang:element(3, Heap)}.
-spec delete_min(heap(FMA)) -> {ok, {FMA, heap(FMA)}} | {error, nil}.
delete_min(Heap) ->
case erlang:element(2, Heap) of
{tree, _, X, A, B} ->
{ok,
{X,
{heap,
merge_trees(A, B, erlang:element(3, Heap)),
erlang:element(3, Heap)}}};
empty ->
{error, nil}
end.
-spec merge(heap(FMF), heap(FMF)) -> heap(FMF).
merge(Heap1, Heap2) ->
Compare = erlang:element(3, Heap1),
{heap,
merge_trees(erlang:element(2, Heap1), erlang:element(2, Heap2), Compare),
Compare}.