1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180# 2 "set.ml"(**************************************************************************)(* *)(* OCaml *)(* *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1996 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)open!Stdlib[@@@ocaml.flambda_o3](* Sets over ordered types *)moduletypeOrderedType=sigtypetvalcompare:t->t->intendmoduletypeS=sigtypeelttypetvalempty:tvaladd:elt->t->tvalsingleton:elt->tvalremove:elt->t->tvalunion:t->t->tvalinter:t->t->tvaldisjoint:t->t->boolvaldiff:t->t->tvalcardinal:t->intvalelements:t->eltlistvalmin_elt:t->eltvalmin_elt_opt:t->eltoptionvalmax_elt:t->eltvalmax_elt_opt:t->eltoptionvalchoose:t->eltvalchoose_opt:t->eltoptionvalfind:elt->t->eltvalfind_opt:elt->t->eltoptionvalfind_first:(elt->bool)->t->eltvalfind_first_opt:(elt->bool)->t->eltoptionvalfind_last:(elt->bool)->t->eltvalfind_last_opt:(elt->bool)->t->eltoptionvaliter:(elt->unit)->t->unitvalfold:(elt->'a->'a)->t->'a->'avalmap:(elt->elt)->t->tvalfilter:(elt->bool)->t->tvalfilter_map:(elt->eltoption)->t->tvalpartition:(elt->bool)->t->t*tvalsplit:elt->t->t*bool*tvalis_empty:t->boolvalmem:elt->t->boolvalequal:t->t->boolvalcompare:t->t->intvalsubset:t->t->boolvalfor_all:(elt->bool)->t->boolvalexists:(elt->bool)->t->boolvalto_list:t->eltlistvalof_list:eltlist->tvalto_seq_from:elt->t->eltSeq.tvalto_seq:t->eltSeq.tvalto_rev_seq:t->eltSeq.tvaladd_seq:eltSeq.t->t->tvalof_seq:eltSeq.t->tendmoduleMake(Ord:OrderedType)=structtypeelt=Ord.ttypet=Empty|Nodeof{l:t;v:elt;r:t;h:int}(* Sets are represented by balanced binary trees (the heights of the
children differ by at most 2 *)letheight=functionEmpty->0|Node{h}->h(* Creates a new node with left son l, value v and right son r.
We must have all elements of l < v < all elements of r.
l and r must be balanced and | height l - height r | <= 2.
Inline expansion of height for better speed. *)letcreatelvr=lethl=matchlwithEmpty->0|Node{h}->hinlethr=matchrwithEmpty->0|Node{h}->hinNode{l;v;r;h=(ifhl>=hrthenhl+1elsehr+1)}(* Same as create, but performs one step of rebalancing if necessary.
Assumes l and r balanced and | height l - height r | <= 3.
Inline expansion of create for better speed in the most frequent case
where no rebalancing is required. *)letballvr=lethl=matchlwithEmpty->0|Node{h}->hinlethr=matchrwithEmpty->0|Node{h}->hinifhl>hr+2thenbeginmatchlwithEmpty->invalid_arg"Set.bal"|Node{l=ll;v=lv;r=lr}->ifheightll>=heightlrthencreatelllv(createlrvr)elsebeginmatchlrwithEmpty->invalid_arg"Set.bal"|Node{l=lrl;v=lrv;r=lrr}->create(createlllvlrl)lrv(createlrrvr)endendelseifhr>hl+2thenbeginmatchrwithEmpty->invalid_arg"Set.bal"|Node{l=rl;v=rv;r=rr}->ifheightrr>=heightrlthencreate(createlvrl)rvrrelsebeginmatchrlwithEmpty->invalid_arg"Set.bal"|Node{l=rll;v=rlv;r=rlr}->create(createlvrll)rlv(createrlrrvrr)endendelseNode{l;v;r;h=(ifhl>=hrthenhl+1elsehr+1)}(* Insertion of one element *)letrecaddx=functionEmpty->Node{l=Empty;v=x;r=Empty;h=1}|Node{l;v;r}ast->letc=Ord.comparexvinifc=0thentelseifc<0thenletll=addxlinifl==llthentelseballlvrelseletrr=addxrinifr==rrthentelseballvrrletsingletonx=Node{l=Empty;v=x;r=Empty;h=1}(* Beware: those two functions assume that the added v is *strictly*
smaller (or bigger) than all the present elements in the tree; it
does not test for equality with the current min (or max) element.
Indeed, they are only used during the "join" operation which
respects this precondition.
*)letrecadd_min_elementx=function|Empty->singletonx|Node{l;v;r}->bal(add_min_elementxl)vrletrecadd_max_elementx=function|Empty->singletonx|Node{l;v;r}->ballv(add_max_elementxr)(* Same as create and bal, but no assumptions are made on the
relative heights of l and r. *)letrecjoinlvr=match(l,r)with(Empty,_)->add_min_elementvr|(_,Empty)->add_max_elementvl|(Node{l=ll;v=lv;r=lr;h=lh},Node{l=rl;v=rv;r=rr;h=rh})->iflh>rh+2thenballllv(joinlrvr)elseifrh>lh+2thenbal(joinlvrl)rvrrelsecreatelvr(* Smallest and greatest element of a set *)letrecmin_elt=functionEmpty->raiseNot_found|Node{l=Empty;v}->v|Node{l}->min_eltlletrecmin_elt_opt=functionEmpty->None|Node{l=Empty;v}->Somev|Node{l}->min_elt_optlletrecmax_elt=functionEmpty->raiseNot_found|Node{v;r=Empty}->v|Node{r}->max_eltrletrecmax_elt_opt=functionEmpty->None|Node{v;r=Empty}->Somev|Node{r}->max_elt_optr(* Remove the smallest element of the given set *)letrecremove_min_elt=functionEmpty->invalid_arg"Set.remove_min_elt"|Node{l=Empty;r}->r|Node{l;v;r}->bal(remove_min_eltl)vr(* Merge two trees l and r into one.
All elements of l must precede the elements of r.
Assume | height l - height r | <= 2. *)letmerget1t2=match(t1,t2)with(Empty,t)->t|(t,Empty)->t|(_,_)->balt1(min_eltt2)(remove_min_eltt2)(* Merge two trees l and r into one.
All elements of l must precede the elements of r.
No assumption on the heights of l and r. *)letconcatt1t2=match(t1,t2)with(Empty,t)->t|(t,Empty)->t|(_,_)->joint1(min_eltt2)(remove_min_eltt2)(* Splitting. split x s returns a triple (l, present, r) where
- l is the set of elements of s that are < x
- r is the set of elements of s that are > x
- present is false if s contains no element equal to x,
or true if s contains an element equal to x. *)letrecsplitx=functionEmpty->(Empty,false,Empty)|Node{l;v;r}->letc=Ord.comparexvinifc=0then(l,true,r)elseifc<0thenlet(ll,pres,rl)=splitxlin(ll,pres,joinrlvr)elselet(lr,pres,rr)=splitxrin(joinlvlr,pres,rr)(* Implementation of the set operations *)letempty=Emptyletis_empty=functionEmpty->true|_->falseletrecmemx=functionEmpty->false|Node{l;v;r}->letc=Ord.comparexvinc=0||memx(ifc<0thenlelser)letrecremovex=functionEmpty->Empty|(Node{l;v;r}ast)->letc=Ord.comparexvinifc=0thenmergelrelseifc<0thenletll=removexlinifl==llthentelseballlvrelseletrr=removexrinifr==rrthentelseballvrrletrecunions1s2=match(s1,s2)with(Empty,t2)->t2|(t1,Empty)->t1|(Node{l=l1;v=v1;r=r1;h=h1},Node{l=l2;v=v2;r=r2;h=h2})->ifh1>=h2thenifh2=1thenaddv2s1elsebeginlet(l2,_,r2)=splitv1s2injoin(unionl1l2)v1(unionr1r2)endelseifh1=1thenaddv1s2elsebeginlet(l1,_,r1)=splitv2s1injoin(unionl1l2)v2(unionr1r2)endletrecinters1s2=match(s1,s2)with(Empty,_)->Empty|(_,Empty)->Empty|(Node{l=l1;v=v1;r=r1},t2)->matchsplitv1t2with(l2,false,r2)->concat(interl1l2)(interr1r2)|(l2,true,r2)->join(interl1l2)v1(interr1r2)(* Same as split, but compute the left and right subtrees
only if the pivot element is not in the set. The right subtree
is computed on demand. *)typesplit_bis=|Found|NotFoundoft*(unit->t)letrecsplit_bisx=functionEmpty->NotFound(Empty,(fun()->Empty))|Node{l;v;r;_}->letc=Ord.comparexvinifc=0thenFoundelseifc<0thenmatchsplit_bisxlwith|Found->Found|NotFound(ll,rl)->NotFound(ll,(fun()->join(rl())vr))elsematchsplit_bisxrwith|Found->Found|NotFound(lr,rr)->NotFound(joinlvlr,rr)letrecdisjoints1s2=match(s1,s2)with(Empty,_)|(_,Empty)->true|(Node{l=l1;v=v1;r=r1},t2)->ifs1==s2thenfalseelsematchsplit_bisv1t2withNotFound(l2,r2)->disjointl1l2&&disjointr1(r2())|Found->falseletrecdiffs1s2=match(s1,s2)with(Empty,_)->Empty|(t1,Empty)->t1|(Node{l=l1;v=v1;r=r1},t2)->matchsplitv1t2with(l2,false,r2)->join(diffl1l2)v1(diffr1r2)|(l2,true,r2)->concat(diffl1l2)(diffr1r2)typeenumeration=End|Moreofelt*t*enumerationletreccons_enumse=matchswithEmpty->e|Node{l;v;r}->cons_enuml(More(v,r,e))letreccompare_auxe1e2=match(e1,e2)with(End,End)->0|(End,_)->-1|(_,End)->1|(More(v1,r1,e1),More(v2,r2,e2))->letc=Ord.comparev1v2inifc<>0thencelsecompare_aux(cons_enumr1e1)(cons_enumr2e2)letcompares1s2=compare_aux(cons_enums1End)(cons_enums2End)letequals1s2=compares1s2=0letrecsubsets1s2=match(s1,s2)withEmpty,_->true|_,Empty->false|Node{l=l1;v=v1;r=r1},(Node{l=l2;v=v2;r=r2}ast2)->letc=Ord.comparev1v2inifc=0thensubsetl1l2&&subsetr1r2elseifc<0thensubset(Node{l=l1;v=v1;r=Empty;h=0})l2&&subsetr1t2elsesubset(Node{l=Empty;v=v1;r=r1;h=0})r2&&subsetl1t2letreciterf=functionEmpty->()|Node{l;v;r}->iterfl;fv;iterfrletrecfoldfsaccu=matchswithEmpty->accu|Node{l;v;r}->foldfr(fv(foldflaccu))letrecfor_allp=functionEmpty->true|Node{l;v;r}->pv&&for_allpl&&for_allprletrecexistsp=functionEmpty->false|Node{l;v;r}->pv||existspl||existsprletrecfilterp=functionEmpty->Empty|(Node{l;v;r})ast->(* call [p] in the expected left-to-right order *)letl'=filterplinletpv=pvinletr'=filterprinifpvthenifl==l'&&r==r'thentelsejoinl'vr'elseconcatl'r'letrecpartitionp=functionEmpty->(Empty,Empty)|Node{l;v;r}->(* call [p] in the expected left-to-right order *)let(lt,lf)=partitionplinletpv=pvinlet(rt,rf)=partitionprinifpvthen(joinltvrt,concatlfrf)else(concatltrt,joinlfvrf)letreccardinal=functionEmpty->0|Node{l;r}->cardinall+1+cardinalrletrecelements_auxaccu=functionEmpty->accu|Node{l;v;r}->elements_aux(v::elements_auxaccur)lletelementss=elements_aux[]sletchoose=min_eltletchoose_opt=min_elt_optletrecfindx=functionEmpty->raiseNot_found|Node{l;v;r}->letc=Ord.comparexvinifc=0thenvelsefindx(ifc<0thenlelser)letrecfind_first_auxv0f=functionEmpty->v0|Node{l;v;r}->iffvthenfind_first_auxvflelsefind_first_auxv0frletrecfind_firstf=functionEmpty->raiseNot_found|Node{l;v;r}->iffvthenfind_first_auxvflelsefind_firstfrletrecfind_first_opt_auxv0f=functionEmpty->Somev0|Node{l;v;r}->iffvthenfind_first_opt_auxvflelsefind_first_opt_auxv0frletrecfind_first_optf=functionEmpty->None|Node{l;v;r}->iffvthenfind_first_opt_auxvflelsefind_first_optfrletrecfind_last_auxv0f=functionEmpty->v0|Node{l;v;r}->iffvthenfind_last_auxvfrelsefind_last_auxv0flletrecfind_lastf=functionEmpty->raiseNot_found|Node{l;v;r}->iffvthenfind_last_auxvfrelsefind_lastflletrecfind_last_opt_auxv0f=functionEmpty->Somev0|Node{l;v;r}->iffvthenfind_last_opt_auxvfrelsefind_last_opt_auxv0flletrecfind_last_optf=functionEmpty->None|Node{l;v;r}->iffvthenfind_last_opt_auxvfrelsefind_last_optflletrecfind_optx=functionEmpty->None|Node{l;v;r}->letc=Ord.comparexvinifc=0thenSomevelsefind_optx(ifc<0thenlelser)lettry_joinlvr=(* [join l v r] can only be called when (elements of l < v <
elements of r); use [try_join l v r] when this property may
not hold, but you hope it does hold in the common case *)if(l=Empty||Ord.compare(max_eltl)v<0)&&(r=Empty||Ord.comparev(min_eltr)<0)thenjoinlvrelseunionl(addvr)letrecmapf=function|Empty->Empty|Node{l;v;r}ast->(* enforce left-to-right evaluation order *)letl'=mapflinletv'=fvinletr'=mapfrinifl==l'&&v==v'&&r==r'thentelsetry_joinl'v'r'lettry_concatt1t2=match(t1,t2)with(Empty,t)->t|(t,Empty)->t|(_,_)->try_joint1(min_eltt2)(remove_min_eltt2)letrecfilter_mapf=function|Empty->Empty|Node{l;v;r}ast->(* enforce left-to-right evaluation order *)letl'=filter_mapflinletv'=fvinletr'=filter_mapfrinbeginmatchv'with|Somev'->ifl==l'&&v==v'&&r==r'thentelsetry_joinl'v'r'|None->try_concatl'r'endletof_sorted_listl=letrecsubnl=matchn,lwith|0,l->Empty,l|1,x0::l->Node{l=Empty;v=x0;r=Empty;h=1},l|2,x0::x1::l->Node{l=Node{l=Empty;v=x0;r=Empty;h=1};v=x1;r=Empty;h=2},l|3,x0::x1::x2::l->Node{l=Node{l=Empty;v=x0;r=Empty;h=1};v=x1;r=Node{l=Empty;v=x2;r=Empty;h=1};h=2},l|n,l->letnl=n/2inletleft,l=subnllinmatchlwith|[]->assertfalse|mid::l->letright,l=sub(n-nl-1)lincreateleftmidright,linfst(sub(List.lengthl)l)letto_list=elementsletof_listl=matchlwith|[]->empty|[x0]->singletonx0|[x0;x1]->addx1(singletonx0)|[x0;x1;x2]->addx2(addx1(singletonx0))|[x0;x1;x2;x3]->addx3(addx2(addx1(singletonx0)))|[x0;x1;x2;x3;x4]->addx4(addx3(addx2(addx1(singletonx0))))|_->of_sorted_list(List.sort_uniqOrd.comparel)letadd_seqim=Seq.fold_left(funsx->addxs)miletof_seqi=add_seqiemptyletrecseq_of_enum_c()=matchcwith|End->Seq.Nil|More(x,t,rest)->Seq.Cons(x,seq_of_enum_(cons_enumtrest))letto_seqc=seq_of_enum_(cons_enumcEnd)letrecsnoc_enumse=matchswithEmpty->e|Node{l;v;r}->snoc_enumr(More(v,l,e))letrecrev_seq_of_enum_c()=matchcwith|End->Seq.Nil|More(x,t,rest)->Seq.Cons(x,rev_seq_of_enum_(snoc_enumtrest))letto_rev_seqc=rev_seq_of_enum_(snoc_enumcEnd)letto_seq_fromlows=letrecauxlowsc=matchswith|Empty->c|Node{l;r;v;_}->beginmatchOrd.comparevlowwith|0->More(v,r,c)|nwhenn<0->auxlowrc|_->auxlowl(More(v,r,c))endinseq_of_enum_(auxlowsEnd)endmoduleMakePortable(Ord:sig@@portableincludeOrderedTypeend)=structtypeelt=Ord.ttypet=Empty|Nodeof{l:t;v:elt;r:t;h:int}(* Sets are represented by balanced binary trees (the heights of the
children differ by at most 2 *)letheight=functionEmpty->0|Node{h}->h(* Creates a new node with left son l, value v and right son r.
We must have all elements of l < v < all elements of r.
l and r must be balanced and | height l - height r | <= 2.
Inline expansion of height for better speed. *)letcreatelvr=lethl=matchlwithEmpty->0|Node{h}->hinlethr=matchrwithEmpty->0|Node{h}->hinNode{l;v;r;h=(ifhl>=hrthenhl+1elsehr+1)}(* Same as create, but performs one step of rebalancing if necessary.
Assumes l and r balanced and | height l - height r | <= 3.
Inline expansion of create for better speed in the most frequent case
where no rebalancing is required. *)letballvr=lethl=matchlwithEmpty->0|Node{h}->hinlethr=matchrwithEmpty->0|Node{h}->hinifhl>hr+2thenbeginmatchlwithEmpty->invalid_arg"Set.bal"|Node{l=ll;v=lv;r=lr}->ifheightll>=heightlrthencreatelllv(createlrvr)elsebeginmatchlrwithEmpty->invalid_arg"Set.bal"|Node{l=lrl;v=lrv;r=lrr}->create(createlllvlrl)lrv(createlrrvr)endendelseifhr>hl+2thenbeginmatchrwithEmpty->invalid_arg"Set.bal"|Node{l=rl;v=rv;r=rr}->ifheightrr>=heightrlthencreate(createlvrl)rvrrelsebeginmatchrlwithEmpty->invalid_arg"Set.bal"|Node{l=rll;v=rlv;r=rlr}->create(createlvrll)rlv(createrlrrvrr)endendelseNode{l;v;r;h=(ifhl>=hrthenhl+1elsehr+1)}(* Insertion of one element *)letrecaddx=functionEmpty->Node{l=Empty;v=x;r=Empty;h=1}|Node{l;v;r}ast->letc=Ord.comparexvinifc=0thentelseifc<0thenletll=addxlinifl==llthentelseballlvrelseletrr=addxrinifr==rrthentelseballvrrletsingletonx=Node{l=Empty;v=x;r=Empty;h=1}(* Beware: those two functions assume that the added v is *strictly*
smaller (or bigger) than all the present elements in the tree; it
does not test for equality with the current min (or max) element.
Indeed, they are only used during the "join" operation which
respects this precondition.
*)letrecadd_min_elementx=function|Empty->singletonx|Node{l;v;r}->bal(add_min_elementxl)vrletrecadd_max_elementx=function|Empty->singletonx|Node{l;v;r}->ballv(add_max_elementxr)(* Same as create and bal, but no assumptions are made on the
relative heights of l and r. *)letrecjoinlvr=match(l,r)with(Empty,_)->add_min_elementvr|(_,Empty)->add_max_elementvl|(Node{l=ll;v=lv;r=lr;h=lh},Node{l=rl;v=rv;r=rr;h=rh})->iflh>rh+2thenballllv(joinlrvr)elseifrh>lh+2thenbal(joinlvrl)rvrrelsecreatelvr(* Smallest and greatest element of a set *)letrecmin_elt=functionEmpty->raiseNot_found|Node{l=Empty;v}->v|Node{l}->min_eltlletrecmin_elt_opt=functionEmpty->None|Node{l=Empty;v}->Somev|Node{l}->min_elt_optlletrecmax_elt=functionEmpty->raiseNot_found|Node{v;r=Empty}->v|Node{r}->max_eltrletrecmax_elt_opt=functionEmpty->None|Node{v;r=Empty}->Somev|Node{r}->max_elt_optr(* Remove the smallest element of the given set *)letrecremove_min_elt=functionEmpty->invalid_arg"Set.remove_min_elt"|Node{l=Empty;r}->r|Node{l;v;r}->bal(remove_min_eltl)vr(* Merge two trees l and r into one.
All elements of l must precede the elements of r.
Assume | height l - height r | <= 2. *)letmerget1t2=match(t1,t2)with(Empty,t)->t|(t,Empty)->t|(_,_)->balt1(min_eltt2)(remove_min_eltt2)(* Merge two trees l and r into one.
All elements of l must precede the elements of r.
No assumption on the heights of l and r. *)letconcatt1t2=match(t1,t2)with(Empty,t)->t|(t,Empty)->t|(_,_)->joint1(min_eltt2)(remove_min_eltt2)(* Splitting. split x s returns a triple (l, present, r) where
- l is the set of elements of s that are < x
- r is the set of elements of s that are > x
- present is false if s contains no element equal to x,
or true if s contains an element equal to x. *)letrecsplitx=functionEmpty->(Empty,false,Empty)|Node{l;v;r}->letc=Ord.comparexvinifc=0then(l,true,r)elseifc<0thenlet(ll,pres,rl)=splitxlin(ll,pres,joinrlvr)elselet(lr,pres,rr)=splitxrin(joinlvlr,pres,rr)(* Implementation of the set operations *)letempty=Emptyletis_empty=functionEmpty->true|_->falseletrecmemx=functionEmpty->false|Node{l;v;r}->letc=Ord.comparexvinc=0||memx(ifc<0thenlelser)letrecremovex=functionEmpty->Empty|(Node{l;v;r}ast)->letc=Ord.comparexvinifc=0thenmergelrelseifc<0thenletll=removexlinifl==llthentelseballlvrelseletrr=removexrinifr==rrthentelseballvrrletrecunions1s2=match(s1,s2)with(Empty,t2)->t2|(t1,Empty)->t1|(Node{l=l1;v=v1;r=r1;h=h1},Node{l=l2;v=v2;r=r2;h=h2})->ifh1>=h2thenifh2=1thenaddv2s1elsebeginlet(l2,_,r2)=splitv1s2injoin(unionl1l2)v1(unionr1r2)endelseifh1=1thenaddv1s2elsebeginlet(l1,_,r1)=splitv2s1injoin(unionl1l2)v2(unionr1r2)endletrecinters1s2=match(s1,s2)with(Empty,_)->Empty|(_,Empty)->Empty|(Node{l=l1;v=v1;r=r1},t2)->matchsplitv1t2with(l2,false,r2)->concat(interl1l2)(interr1r2)|(l2,true,r2)->join(interl1l2)v1(interr1r2)(* Same as split, but compute the left and right subtrees
only if the pivot element is not in the set. The right subtree
is computed on demand. *)typesplit_bis=|Found|NotFoundoft*(unit->t)letrecsplit_bisx=functionEmpty->NotFound(Empty,(fun()->Empty))|Node{l;v;r;_}->letc=Ord.comparexvinifc=0thenFoundelseifc<0thenmatchsplit_bisxlwith|Found->Found|NotFound(ll,rl)->NotFound(ll,(fun()->join(rl())vr))elsematchsplit_bisxrwith|Found->Found|NotFound(lr,rr)->NotFound(joinlvlr,rr)letrecdisjoints1s2=match(s1,s2)with(Empty,_)|(_,Empty)->true|(Node{l=l1;v=v1;r=r1},t2)->ifs1==s2thenfalseelsematchsplit_bisv1t2withNotFound(l2,r2)->disjointl1l2&&disjointr1(r2())|Found->falseletrecdiffs1s2=match(s1,s2)with(Empty,_)->Empty|(t1,Empty)->t1|(Node{l=l1;v=v1;r=r1},t2)->matchsplitv1t2with(l2,false,r2)->join(diffl1l2)v1(diffr1r2)|(l2,true,r2)->concat(diffl1l2)(diffr1r2)typeenumeration=End|Moreofelt*t*enumerationletreccons_enumse=matchswithEmpty->e|Node{l;v;r}->cons_enuml(More(v,r,e))letreccompare_auxe1e2=match(e1,e2)with(End,End)->0|(End,_)->-1|(_,End)->1|(More(v1,r1,e1),More(v2,r2,e2))->letc=Ord.comparev1v2inifc<>0thencelsecompare_aux(cons_enumr1e1)(cons_enumr2e2)letcompares1s2=compare_aux(cons_enums1End)(cons_enums2End)letequals1s2=compares1s2=0letrecsubsets1s2=match(s1,s2)withEmpty,_->true|_,Empty->false|Node{l=l1;v=v1;r=r1},(Node{l=l2;v=v2;r=r2}ast2)->letc=Ord.comparev1v2inifc=0thensubsetl1l2&&subsetr1r2elseifc<0thensubset(Node{l=l1;v=v1;r=Empty;h=0})l2&&subsetr1t2elsesubset(Node{l=Empty;v=v1;r=r1;h=0})r2&&subsetl1t2letreciterf=functionEmpty->()|Node{l;v;r}->iterfl;fv;iterfrletrecfoldfsaccu=matchswithEmpty->accu|Node{l;v;r}->foldfr(fv(foldflaccu))letrecfor_allp=functionEmpty->true|Node{l;v;r}->pv&&for_allpl&&for_allprletrecexistsp=functionEmpty->false|Node{l;v;r}->pv||existspl||existsprletrecfilterp=functionEmpty->Empty|(Node{l;v;r})ast->(* call [p] in the expected left-to-right order *)letl'=filterplinletpv=pvinletr'=filterprinifpvthenifl==l'&&r==r'thentelsejoinl'vr'elseconcatl'r'letrecpartitionp=functionEmpty->(Empty,Empty)|Node{l;v;r}->(* call [p] in the expected left-to-right order *)let(lt,lf)=partitionplinletpv=pvinlet(rt,rf)=partitionprinifpvthen(joinltvrt,concatlfrf)else(concatltrt,joinlfvrf)letreccardinal=functionEmpty->0|Node{l;r}->cardinall+1+cardinalrletrecelements_auxaccu=functionEmpty->accu|Node{l;v;r}->elements_aux(v::elements_auxaccur)lletelementss=elements_aux[]sletchoose=min_eltletchoose_opt=min_elt_optletrecfindx=functionEmpty->raiseNot_found|Node{l;v;r}->letc=Ord.comparexvinifc=0thenvelsefindx(ifc<0thenlelser)letrecfind_first_auxv0f=functionEmpty->v0|Node{l;v;r}->iffvthenfind_first_auxvflelsefind_first_auxv0frletrecfind_firstf=functionEmpty->raiseNot_found|Node{l;v;r}->iffvthenfind_first_auxvflelsefind_firstfrletrecfind_first_opt_auxv0f=functionEmpty->Somev0|Node{l;v;r}->iffvthenfind_first_opt_auxvflelsefind_first_opt_auxv0frletrecfind_first_optf=functionEmpty->None|Node{l;v;r}->iffvthenfind_first_opt_auxvflelsefind_first_optfrletrecfind_last_auxv0f=functionEmpty->v0|Node{l;v;r}->iffvthenfind_last_auxvfrelsefind_last_auxv0flletrecfind_lastf=functionEmpty->raiseNot_found|Node{l;v;r}->iffvthenfind_last_auxvfrelsefind_lastflletrecfind_last_opt_auxv0f=functionEmpty->Somev0|Node{l;v;r}->iffvthenfind_last_opt_auxvfrelsefind_last_opt_auxv0flletrecfind_last_optf=functionEmpty->None|Node{l;v;r}->iffvthenfind_last_opt_auxvfrelsefind_last_optflletrecfind_optx=functionEmpty->None|Node{l;v;r}->letc=Ord.comparexvinifc=0thenSomevelsefind_optx(ifc<0thenlelser)lettry_joinlvr=(* [join l v r] can only be called when (elements of l < v <
elements of r); use [try_join l v r] when this property may
not hold, but you hope it does hold in the common case *)if(l=Empty||Ord.compare(max_eltl)v<0)&&(r=Empty||Ord.comparev(min_eltr)<0)thenjoinlvrelseunionl(addvr)letrecmapf=function|Empty->Empty|Node{l;v;r}ast->(* enforce left-to-right evaluation order *)letl'=mapflinletv'=fvinletr'=mapfrinifl==l'&&v==v'&&r==r'thentelsetry_joinl'v'r'lettry_concatt1t2=match(t1,t2)with(Empty,t)->t|(t,Empty)->t|(_,_)->try_joint1(min_eltt2)(remove_min_eltt2)letrecfilter_mapf=function|Empty->Empty|Node{l;v;r}ast->(* enforce left-to-right evaluation order *)letl'=filter_mapflinletv'=fvinletr'=filter_mapfrinbeginmatchv'with|Somev'->ifl==l'&&v==v'&&r==r'thentelsetry_joinl'v'r'|None->try_concatl'r'endletof_sorted_listl=letrecsubnl=matchn,lwith|0,l->Empty,l|1,x0::l->Node{l=Empty;v=x0;r=Empty;h=1},l|2,x0::x1::l->Node{l=Node{l=Empty;v=x0;r=Empty;h=1};v=x1;r=Empty;h=2},l|3,x0::x1::x2::l->Node{l=Node{l=Empty;v=x0;r=Empty;h=1};v=x1;r=Node{l=Empty;v=x2;r=Empty;h=1};h=2},l|n,l->letnl=n/2inletleft,l=subnllinmatchlwith|[]->assertfalse|mid::l->letright,l=sub(n-nl-1)lincreateleftmidright,linfst(sub(List.lengthl)l)letto_list=elementsletof_listl=matchlwith|[]->Empty|[x0]->singletonx0|[x0;x1]->addx1(singletonx0)|[x0;x1;x2]->addx2(addx1(singletonx0))|[x0;x1;x2;x3]->addx3(addx2(addx1(singletonx0)))|[x0;x1;x2;x3;x4]->addx4(addx3(addx2(addx1(singletonx0))))|_->of_sorted_list(List.sort_uniqOrd.comparel)letadd_seqim=Seq.fold_left(funsx->addxs)miletof_seqi=add_seqiEmptyletrecseq_of_enum_c()=matchcwith|End->Seq.Nil|More(x,t,rest)->Seq.Cons(x,seq_of_enum_(cons_enumtrest))letto_seqc=seq_of_enum_(cons_enumcEnd)letrecsnoc_enumse=matchswithEmpty->e|Node{l;v;r}->snoc_enumr(More(v,l,e))letrecrev_seq_of_enum_c()=matchcwith|End->Seq.Nil|More(x,t,rest)->Seq.Cons(x,rev_seq_of_enum_(snoc_enumtrest))letto_rev_seqc=rev_seq_of_enum_(snoc_enumcEnd)letto_seq_fromlows=letrecauxlowsc=matchswith|Empty->c|Node{l;r;v;_}->beginmatchOrd.comparevlowwith|0->More(v,r,c)|nwhenn<0->auxlowrc|_->auxlowl(More(v,r,c))endinseq_of_enum_(auxlowsEnd)end[@@inlineavailable]