123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342(*
*
* Copyright (c) 2001-2002,
* John Kodumal <jkodumal@eecs.berkeley.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The names of the contributors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*)(***********************************************************************)(* *)(* Objective Caml *)(* *)(* 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 Library General Public License, with *)(* the special exception on linking described in file ../LICENSE. *)(* *)(***********************************************************************)(* $Id$ *)(* Sets over ordered types *)moduletypePolyOrderedType=sigtype'atvalcompare:'at->'at->intendmoduletypeS=sigtype'aelttype'atvalempty:'atvalis_empty:'at->boolvalmem:'aelt->'at->boolvaladd:'aelt->'at->'atvalsingleton:'aelt->'atvalremove:'aelt->'at->'atvalunion:'at->'at->'atvalinter:'at->'at->'atvaldiff:'at->'at->'atvalcompare:'at->'at->intvalequal:'at->'at->boolvalsubset:'at->'at->boolvaliter:('aelt->unit)->'at->unitvalfold:('aelt->'b->'b)->'at->'b->'bvalfor_all:('aelt->bool)->'at->boolvalexists:('aelt->bool)->'at->boolvalfilter:('aelt->bool)->'at->'atvalpartition:('aelt->bool)->'at->'at*'atvalcardinal:'at->intvalelements:'at->'aeltlistvalmin_elt:'at->'aeltvalmax_elt:'at->'aeltvalchoose:'at->'aeltendmoduleMake(Ord:PolyOrderedType)=structtype'aelt='aOrd.ttype'at=Empty|Nodeof'at*'aelt*'at*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 x and right son r.
l and r must be balanced and | height l - height r | <= 2.
Inline expansion of height for better speed. *)letcreatelxr=lethl=matchlwithEmpty->0|Node(_,_,_,h)->hinlethr=matchrwithEmpty->0|Node(_,_,_,h)->hinNode(l,x,r,(ifhl>=hrthenhl+1elsehr+1))(* Same as create, but performs one step of rebalancing if necessary.
Assumes l and r balanced.
Inline expansion of create for better speed in the most frequent case
where no rebalancing is required. *)letballxr=lethl=matchlwithEmpty->0|Node(_,_,_,h)->hinlethr=matchrwithEmpty->0|Node(_,_,_,h)->hinifhl>hr+2thenbeginmatchlwithEmpty->invalid_arg"Set.bal"|Node(ll,lv,lr,_)->ifheightll>=heightlrthencreatelllv(createlrxr)elsebeginmatchlrwithEmpty->invalid_arg"Set.bal"|Node(lrl,lrv,lrr,_)->create(createlllvlrl)lrv(createlrrxr)endendelseifhr>hl+2thenbeginmatchrwithEmpty->invalid_arg"Set.bal"|Node(rl,rv,rr,_)->ifheightrr>=heightrlthencreate(createlxrl)rvrrelsebeginmatchrlwithEmpty->invalid_arg"Set.bal"|Node(rll,rlv,rlr,_)->create(createlxrll)rlv(createrlrrvrr)endendelseNode(l,x,r,(ifhl>=hrthenhl+1elsehr+1))(* Same as bal, but repeat rebalancing until the final result
is balanced. *)letrecjoinlxr=matchballxrwithEmpty->invalid_arg"Set.join"|Node(l',x',r',_)ast'->letd=heightl'-heightr'inifd<-2||d>2thenjoinl'x'r'elset'(* Merge two trees l and r into one.
All elements of l must precede the elements of r.
Assumes | height l - height r | <= 2. *)letrecmerget1t2=match(t1,t2)with(Empty,t)->t|(t,Empty)->t|(Node(l1,v1,r1,h1),Node(l2,v2,r2,h2))->ball1v1(bal(merger1l2)v2r2)(* Same as merge, but does not assume anything about l and r. *)letrecconcatt1t2=match(t1,t2)with(Empty,t)->t|(t,Empty)->t|(Node(l1,v1,r1,h1),Node(l2,v2,r2,h2))->joinl1v1(join(concatr1l2)v2r2)(* Splitting *)letrecsplitx=functionEmpty->(Empty,None,Empty)|Node(l,v,r,_)->letc=Ord.comparexvinifc=0then(l,Somev,r)elseifc<0thenlet(ll,vl,rl)=splitxlin(ll,vl,joinrlvr)elselet(lr,vr,rr)=splitxrin(joinlvlr,vr,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)letrecaddx=functionEmpty->Node(Empty,x,Empty,1)|Node(l,v,r,_)ast->letc=Ord.comparexvinifc=0thentelseifc<0thenbal(addxl)vrelseballv(addxr)letsingletonx=Node(Empty,x,Empty,1)letrecremovex=functionEmpty->Empty|Node(l,v,r,_)->letc=Ord.comparexvinifc=0thenmergelrelseifc<0thenbal(removexl)vrelseballv(removexr)letrecunions1s2=match(s1,s2)with(Empty,t2)->t2|(t1,Empty)->t1|(Node(l1,v1,r1,h1),Node(l2,v2,r2,h2))->ifh1>=h2thenifh2=1thenaddv2s1elsebeginlet(l2,_,r2)=splitv1s2injoin(unionl1l2)v1(unionr1r2)endelseifh1=1thenaddv1s2elsebeginlet(l1,_,r1)=splitv2s1injoin(unionl1l2)v2(unionr1r2)endletrecinters1s2=match(s1,s2)with(Empty,t2)->Empty|(t1,Empty)->Empty|(Node(l1,v1,r1,_),t2)->matchsplitv1t2with(l2,None,r2)->concat(interl1l2)(interr1r2)|(l2,Some_,r2)->join(interl1l2)v1(interr1r2)letrecdiffs1s2=match(s1,s2)with(Empty,t2)->Empty|(t1,Empty)->t1|(Node(l1,v1,r1,_),t2)->matchsplitv1t2with(l2,None,r2)->join(diffl1l2)v1(diffr1r2)|(l2,Some_,r2)->concat(diffl1l2)(diffr1r2)letreccompare_auxl1l2=match(l1,l2)with([],[])->0|([],_)->-1|(_,[])->1|(Empty::t1,Empty::t2)->compare_auxt1t2|(Node(Empty,v1,r1,_)::t1,Node(Empty,v2,r2,_)::t2)->letc=Ord.comparev1v2inifc<>0thencelsecompare_aux(r1::t1)(r2::t2)|(Node(l1,v1,r1,_)::t1,t2)->compare_aux(l1::Node(Empty,v1,r1,0)::t1)t2|(t1,Node(l2,v2,r2,_)::t2)->compare_auxt1(l2::Node(Empty,v2,r2,0)::t2)letcompares1s2=compare_aux[s1][s2]letequals1s2=compares1s2=0letrecsubsets1s2=match(s1,s2)withEmpty,_->true|_,Empty->false|Node(l1,v1,r1,_),(Node(l2,v2,r2,_)ast2)->letc=Ord.comparev1v2inifc=0thensubsetl1l2&&subsetr1r2elseifc<0thensubset(Node(l1,v1,Empty,0))l2&&subsetr1t2elsesubset(Node(Empty,v1,r1,0))r2&&subsetl1t2letreciterf=functionEmpty->()|Node(l,v,r,_)->iterfl;fv;iterfrletrecfoldfsaccu=matchswithEmpty->accu|Node(l,v,r,_)->foldfl(fv(foldfraccu))letrecfor_allp=functionEmpty->true|Node(l,v,r,_)->pv&&for_allpl&&for_allprletrecexistsp=functionEmpty->false|Node(l,v,r,_)->pv||existspl||existsprletfilterps=letrecfiltaccu=function|Empty->accu|Node(l,v,r,_)->filt(filt(ifpvthenaddvaccuelseaccu)l)rinfiltEmptysletpartitionps=letrecpart(t,fasaccu)=function|Empty->accu|Node(l,v,r,_)->part(part(ifpvthen(addvt,f)else(t,addvf))l)rinpart(Empty,Empty)sletreccardinal=functionEmpty->0|Node(l,v,r,_)->cardinall+1+cardinalrletrecelements_auxaccu=functionEmpty->accu|Node(l,v,r,_)->elements_aux(v::elements_auxaccur)lletelementss=elements_aux[]sletrecmin_elt=functionEmpty->raiseNot_found|Node(Empty,v,r,_)->v|Node(l,v,r,_)->min_eltlletrecmax_elt=functionEmpty->raiseNot_found|Node(l,v,Empty,_)->v|Node(l,v,r,_)->max_eltrletchoose=min_eltend