94 lines
2.8 KiB
Plaintext
94 lines
2.8 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_element) ;
|
|
|
|
function is_empty (const h : heap) : bool is
|
|
block {skip} with size(h) = 0n
|
|
|
|
function get_top (const h : heap) : heap_element is
|
|
block {skip} with get_force(1n, h)
|
|
|
|
function pop_switch (const h : heap) : heap is
|
|
block {
|
|
const result : heap_element = get_top (h) ;
|
|
const s : nat = size(h) ;
|
|
const last : heap_element = get_force(s, h) ;
|
|
remove 1n from map h ;
|
|
h[1n] := last ;
|
|
} with h
|
|
|
|
function pop_ (const h : heap) : nat is
|
|
begin
|
|
const result : heap_element = get_top (h) ;
|
|
const s : nat = size(h) ;
|
|
var current : heap_element := get_force(s, h) ;
|
|
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 ;
|
|
if (left <= s and heap_element_lt(get_force(s , h) , get_force(left , h))) then
|
|
largest := left
|
|
else if (right <= s and heap_element_lt(get_force(s , h) , get_force(right , h))) then
|
|
largest := right
|
|
else skip
|
|
end with largest
|
|
|
|
function insert (const h : heap ; const e : heap_element) : heap is
|
|
begin
|
|
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 block {
|
|
if (heap_element_lt(get_force(parent , h) , get_force(i , h))) then block {
|
|
largest := parent ;
|
|
const tmp : heap_element = get_force(i , h) ;
|
|
h[i] := get_force(parent , h) ;
|
|
h[parent] := tmp ;
|
|
} else skip
|
|
} else skip
|
|
}
|
|
end with h
|
|
|
|
function pop (const h : heap) : (heap * heap_element * nat) is
|
|
begin
|
|
const result : heap_element = get_top (h) ;
|
|
var s : nat := size(h) ;
|
|
const last : heap_element = 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 begin
|
|
if (heap_element_lt(get_force(left , h) , get_force(i , h))) then begin
|
|
largest := left ;
|
|
const tmp : heap_element = get_force(i , h) ;
|
|
h[i] := get_force(left , h) ;
|
|
h[left] := tmp ;
|
|
end else skip ;
|
|
end else if (right <= s) then begin
|
|
if (heap_element_lt(get_force(right , h) , get_force(i , h))) then begin
|
|
largest := right ;
|
|
const tmp : heap_element = get_force(i , h) ;
|
|
h[i] := get_force(right , h) ;
|
|
h[left] := tmp ;
|
|
end else skip ;
|
|
end else skip ;
|
|
}
|
|
end with (h , result , c)
|