104 lines
2.9 KiB
Plaintext
104 lines
2.9 KiB
Plaintext
// Implementation of the heap data structure in PascaLIGO
|
|
// See: https://en.wikipedia.org/wiki/Heap_%28data_structure%29
|
|
|
|
type heap is map (nat, heap_elt)
|
|
|
|
function is_empty (const h : heap) : bool is size (h) = 0n
|
|
|
|
function get_top (const h : heap) : heap_elt is get_force (1n, h)
|
|
|
|
function pop_switch (const h : heap) : heap is
|
|
block {
|
|
const result : heap_elt = get_top (h);
|
|
const s : nat = Map.size (h);
|
|
const last : heap_elt =
|
|
case h[s] of
|
|
Some (e) -> e
|
|
| None -> (failwith ("No element.") : heap_elt)
|
|
end;
|
|
remove 1n from map h;
|
|
h[1n] := last
|
|
} with h
|
|
|
|
function pop_ (const h : heap) : nat is
|
|
block {
|
|
const result : heap_elt = get_top (h);
|
|
const s : nat = Map.size (h);
|
|
var current : heap_elt :=
|
|
case h[s] of
|
|
Some (e) -> e
|
|
| None -> (failwith ("No element.") : heap_elt)
|
|
end;
|
|
const i : nat = 1n;
|
|
const left : nat = 2n * i;
|
|
const right : nat = left + 1n;
|
|
remove 1n from map h;
|
|
h[1n] := current;
|
|
var largest : nat := i;
|
|
const tmp : heap_elt = get_force (s, h);
|
|
if left <= s and heap_elt_lt (tmp, get_force (left,h))
|
|
then largest := left
|
|
else
|
|
if right <= s and heap_elt_lt (tmp, get_force (right,h))
|
|
then largest := right
|
|
else skip
|
|
} with largest
|
|
|
|
function insert (const h : heap ; const e : heap_elt) : heap is
|
|
block {
|
|
var i : nat := size (h) + 1n;
|
|
h[i] := e;
|
|
var largest : nat := i;
|
|
var parent : nat := 0n;
|
|
while largest =/= i block {
|
|
parent := i/2n;
|
|
largest := i;
|
|
if parent >= 1n then {
|
|
if heap_elt_lt (get_force (parent,h), get_force(i,h))) then {
|
|
largest := parent;
|
|
const tmp : heap_elt = get_force (i,h);
|
|
h[i] := get_force(parent, h);
|
|
h[parent] := tmp
|
|
} else skip
|
|
} else skip
|
|
}
|
|
} with h
|
|
|
|
function pop (const h : heap) : heap * heap_elt * nat is
|
|
block {
|
|
const result : heap_elt = get_top (h);
|
|
var s : nat := size (h);
|
|
const last : heap_elt = get_force (s,h);
|
|
remove s from map h;
|
|
h[1n] := last;
|
|
s := size (h);
|
|
var i : nat := 0n;
|
|
var largest : nat := 1n;
|
|
var left : nat := 0n;
|
|
var right : nat := 0n;
|
|
var c : nat := 0n;
|
|
while largest =/= i block {
|
|
c := c + 1n;
|
|
i := largest;
|
|
left := 2n * i;
|
|
right := left + 1n;
|
|
if left <= s then {
|
|
if heap_elt_lt (get_force (left,h), get_force(i,h)) then {
|
|
largest := left;
|
|
const tmp : heap_elt = get_force(i,h);
|
|
h[i] := get_force (left, h);
|
|
h[left] := tmp
|
|
} else skip
|
|
}
|
|
else
|
|
if right <= s then {
|
|
if heap_elt_lt (get_force (right, h), get_force (i,h)) then {
|
|
largest := right;
|
|
const tmp : heap_elt = get_force (i,h);
|
|
h[i] := get_force (right, h);
|
|
h[left] := tmp
|
|
} else skip
|
|
} else skip
|
|
}
|
|
} with (h, result, c)
|