Binary Search Tree set of int
, very much like Stdlib.Set
without the balancing stuff.
(This code is outrageous plagiarism of Stdlib.Set.ml
)
type t =
| Empty
| Fork of t * int * t
let empty =
Empty
let is_empty t =
t = Empty
let singleton n =
Fork(Empty,n,Empty)
let rec strahler = function
| Empty -> 0
| Fork(l,n,r) ->
let sl = strahler l and sr = strahler r in
if sl = sr then sl+1 else max sl sr
let rec add n t =
match t with
| Empty -> singleton n
| Fork(l,m,r) ->
if n < m then Fork(add n l,m,r)
else if n > m then Fork(l,m,add n r)
else t
let rec member n = function
| Empty -> false
| Fork(l,m,r) ->
if n < m then member n l
else if n > m then member n r
else true
let rec interval low high = function
| Empty -> Empty
| Fork(l,n,r) ->
if high < n then interval low high l
else if low > n then interval low high r
else Fork(interval low high l,n,interval low high r)
let rec cardinal = function
| Empty -> 0
| Fork(l,_,r) -> cardinal l + 1 + cardinal r
let rec cardinal acc = function
| Empty -> acc
| Fork(l,_,r) -> cardinal (cardinal acc r + 1) l
let cardinal =
cardinal 0
let rec minimum acc = function
| Empty -> acc
| Fork(l,n,r) -> minimum n l
let rec remove_minimum la na ra =
match la with
| Empty -> ra
| Fork(lb,nb,rb) -> Fork(remove_minimum lb nb rb,na,ra)
let concat ta tb =
match ta,tb with
| _,Empty -> ta
| Empty,_ -> tb
| _,Fork(lb,nb,rb) ->
Fork(ta,minimum nb lb,remove_minimum lb nb rb)
let rec remove n = function
| Empty -> Empty
| Fork(l,m,r) ->
if n < m then Fork(remove n l,m,r)
else if n > m then Fork(l,m,remove n r)
else concat l r
let rec filter cond = function
| Empty -> Empty
| Fork(l,n,r) ->
if cond n then Fork(filter cond l,n,filter cond r)
else concat (filter cond l) (filter cond r)
let rec split n = function
| Empty -> Empty,false,Empty
| Fork(l,m,r) ->
if n < m then
let la,present,ra = split n l in la,present,Fork(ra,m,r)
else if n > m then
let lb,present,rb = split n r in Fork(l,m,lb),present,rb
else l,true,r
let rec union ta tb =
match ta,tb with
| _,Empty -> ta
| Empty,_ -> tb
| Fork(la,na,ra),_ ->
let lb,_,rb = split na tb
in Fork(union la lb,na,union ra rb)
let rec intersection ta tb =
match ta,tb with
| _,Empty | Empty,_ -> Empty
| Fork(la,na,ra),_ ->
let lb,present,rb = split na tb in
if present then Fork(intersection la lb,na,intersection ra rb)
else concat (intersection la lb) (intersection ra rb)
let rec difference ta tb =
match ta,tb with
| _,Empty -> ta
| Empty,_ -> Empty
| Fork(la,na,ra),_ ->
let lb,present,rb = split na tb in
if present then concat (difference la lb) (difference ra rb)
else Fork(difference la lb,na,difference ra rb)
let rec disjoint ta tb =
match ta,tb with
| _,Empty | Empty,_ -> true
| Fork(la,na,ra),_ ->
let lb,present,rb = split na tb in
if present then false
else disjoint la lb && disjoint ra rb
let rec subset ta tb =
match ta,tb with
| Empty,_ -> true
| _,Empty -> false
| Fork(la,na,ra),Fork(lb,nb,rb) ->
if na < nb then
subset (Fork(la,na,Empty)) lb && subset ra tb
else if na > nb then
subset (Fork(Empty,na,ra)) rb && subset la tb
else
subset la lb && subset ra rb
let equal ta tb =
subset ta tb && subset tb ta
(* recursive linearization *)
let rec to_list = function
| Empty -> []
| Fork(l,n,r) -> to_list l @ [n] @ to_list r
(* iterative linearization *)
let rec to_list acc = function
| Empty -> acc
| Fork(l,n,r) -> to_list (n::to_list acc r) l
let to_list =
to_list []