mirror of
https://github.com/c-cube/nanoev.git
synced 2026-03-13 17:16:23 -04:00
61 lines
1.4 KiB
OCaml
61 lines
1.4 KiB
OCaml
type 'a tree =
|
|
| E
|
|
| N of int * 'a * 'a tree * 'a tree
|
|
|
|
type 'a t = {
|
|
leq: 'a -> 'a -> bool;
|
|
mutable t: 'a tree;
|
|
}
|
|
|
|
let create ~leq () : _ t = { leq; t = E }
|
|
|
|
let[@inline] is_empty (self : _ t) =
|
|
match self.t with
|
|
| E -> true
|
|
| N _ -> false
|
|
|
|
exception Empty
|
|
|
|
open struct
|
|
(** Rank of the tree *)
|
|
let[@inline] rank_ = function
|
|
| E -> 0
|
|
| N (r, _, _, _) -> r
|
|
|
|
(** Make a balanced node labelled with [x], and subtrees [a] and [b].
|
|
We ensure that the right child's rank is ≤ to the rank of the
|
|
left child (leftist property). The rank of the resulting node
|
|
is the length of the rightmost path. *)
|
|
let[@inline] mk_node_ x a b =
|
|
if rank_ a >= rank_ b then
|
|
N (rank_ b + 1, x, a, b)
|
|
else
|
|
N (rank_ a + 1, x, b, a)
|
|
|
|
let rec merge ~leq t1 t2 =
|
|
match t1, t2 with
|
|
| t, E -> t
|
|
| E, t -> t
|
|
| N (_, x, a1, b1), N (_, y, a2, b2) ->
|
|
if leq x y then
|
|
mk_node_ x a1 (merge ~leq b1 t2)
|
|
else
|
|
mk_node_ y a2 (merge ~leq t1 b2)
|
|
end
|
|
|
|
let clear self = self.t <- E
|
|
|
|
let[@inline] insert (self : _ t) x : unit =
|
|
self.t <- merge ~leq:self.leq self.t (N (1, x, E, E))
|
|
|
|
let[@inline] peek_min_exn (self : _ t) =
|
|
match self.t with
|
|
| E -> raise Empty
|
|
| N (_, x, _, _) -> x
|
|
|
|
let[@inline] pop_min_exn (self : _ t) =
|
|
match self.t with
|
|
| E -> raise Empty
|
|
| N (_, x, l, r) ->
|
|
self.t <- merge ~leq:self.leq l r;
|
|
x
|