123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379(*
* Heap -- binomial heaps
* Copyright (C) 2011 Batteries Included Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)letminxy=ifx<=ythenxelsey(** binomial trees*)type'abt={rank:int;root:'a;kids:'abtlist;}type'at={size :int;data:'abtlist;mind:'aoption ;(** cached minimal element *)}letempty={size=0;data=[];mind=None}letsizebh=bh.sizeletlinkbt1bt2 =assert(bt1.rank=bt2.rank);letrank=bt1.rank+1inletleq =bt1.root<=bt2.root inletroot=ifleqthenbt1.rootelsebt2.rootinletkids=ifleqthenbt2::bt1.kidselsebt1::bt2.kidsin{rank =rank ;root=root;kids=kids}letrecadd_treet=function|[]->[t]|(ut::uts)asts->assert(t.rank<=ut.rank);ift.rank<ut.rankthent::tselseadd_tree(link tut)utsletinsertbhx=letsize=bh.size+1inlet data=add_tree{rank=0;root=x;kids=[]}bh.datainletmind=matchbh.mindwith|None->Somex|Somemind->Some(minxmind)in{size=size ;data=data;mind=mind}(*$T size ; empty
size (insert empty 3) = 1
size empty = 0
*)letaddxbh=insertbhx(*$T
find_min (add 3 (add 2 (add 1 empty))) = 1
*)letrecmerge_datats1ts2=matchts1,ts2with|_,[]->ts1|[],_->ts2|t1::tss1,t2::tss2->if t1.rank<t2.rankthent1:: merge_datatss1ts2elseift1.rank >t2.rankthent2:: merge_datats1tss2elseadd_tree(linkt1t2)(merge_datatss1tss2)letmergebh1bh2=letsize=bh1.size +bh2.size inletdata=merge_databh1.data bh2.datainlet mind=matchbh1.mind,bh2.mindwith|Somem1,Somem2->Some(minm1m2)|m,None|None,m->min{size=size;data=data;mind=mind}(*$T
merge (of_list [3;2]) (of_list [4;1]) |> to_list = [1;2;3;4]
*)letfind_minbh=matchbh.mindwith|None-> invalid_arg"find_min"|Somed->d(*$T find_min; insert ; empty
find_min (insert (insert empty 3) 5) = 3
find_min (insert (insert empty 5) 3) = 3
*)letrecfind_min_treets~kfail~ksuccess=matchtswith|[]->kfail()|[t]->ksuccesst|t::ts->find_min_treets~kfail~ksuccess:(funu->ift.root<=u.rootthenksuccesstelseksuccessu)letrecdel_min_treebts~kfail~ksuccess=matchbtswith|[]->kfail()|[t]->ksuccesst[]|t::ts->del_min_treets~kfail~ksuccess:(funuuts->ift.root <=u.rootthenksuccessttselseksuccessu(t::uts))letdel_min bh=letkfail()=invalid_arg "del_min"indel_min_tree bh.data~kfail~ksuccess:(funbtdata ->letsize=bh.size-1inletdata=merge_data(List.revbt.kids)datainletmind=ifsize=0thenNoneelseSome(find_min_treedata~kfail~ksuccess:(funt->t)).rootin{size;data;mind})letof_listl=List.fold_leftinsertemptylletto_listbh=letrecauxaccbh=ifsizebh=0thenaccelseletm=find_min bhinletbh=del_minbhinaux(m::acc)bhinList.rev(aux[]bh)(*$T to_list ; empty
to_list (insert (insert empty 4) 6) = [4; 6]
to_list (insert (insert empty 6) 4) = [4; 6]
to_list empty = []
*)(*$Q to_list ; insert ; empty
(Q.list Q.int) ~count:10 (fun l -> to_list (List.fold_left insert empty l) = List.sort compare l)
*)letelems=to_listletprint?(first="[")?(last="]")?(sep="; ")elepr outbh=letrecspin bh=ifsizebh=0then()elseifsizebh=1theneleprout(find_minbh)else begineleprout(find_minbh);BatInnerIO.nwriteoutsep;spin(del_min bh)endinBatInnerIO.nwriteoutfirst;spinbh;BatInnerIO.nwrite outlastletrecenum bh=letcur=refbhinletnext ()=letbh=!cur inifsizebh=0thenraiseBatEnum.No_more_elements;cur:=(del_minbh);find_min bhinletcount()=size!curinletclone()=enum!curinBatEnum.make~next ~count~cloneletof_enume=BatEnum.foldinsertemptye(*$Q
(Q.list Q.small_int) (fun l -> \
of_list l |> enum |> List.of_enum = List.sort Int.compare l)
*)moduletypeH=sigtypeelemtypetvalempty:tvalsize:t->intvalinsert:t->elem->tvaladd:elem ->t->tvalmerge:t->t->tvalfind_min:t->elemvaldel_min:t->tvalof_list:elem list->tvalto_list:t->elemlistvalelems:t->elemlistvalof_enum:elem BatEnum.t->tvalenum:t->elemBatEnum.tvalprint:?first:string->?last:string->?sep:string-> ('aBatInnerIO.output->elem->unit)->'aBatInnerIO.output->t->unitendmodule Make(Ord :BatInterfaces.OrderedType)=structtypeelem=Ord.tletord_minxy=ifOrd.comparexy<=0thenxelseytype bt={rank:int;root:Ord.t;kids:btlist;}typet={size :int;data:btlist;mind:Ord.toption ;}letempty={size =0;data=[];mind=None}letsizebh=bh.sizeletlinkbt1bt2=assert(bt1.rank =bt2.rank);letrank=bt1.rank+1inletleq=Ord.comparebt1.root bt2.root<=0inletroot=ifleqthenbt1.rootelsebt2.rootinletkids=ifleqthenbt2::bt1.kidselsebt1::bt2.kidsin{rank=rank;root=root;kids=kids}let recadd_treet=function|[]->[t]|(ut::uts)asts->assert(t.rank <=ut.rank);ift.rank <ut.rankthent::tselseadd_tree(linktut)utsletinsertbh x=letdata=add_tree {rank=0;root=x;kids=[]}bh.datainletmind=matchbh.mindwith|None->Somex|Somemind->Some(ord_minxmind)in{size=bh.size+1;data=data;mind=mind}letaddxbh =insertbhxletrecmerge_datats1ts2=matchts1,ts2with|_,[]->ts1|[],_->ts2|t1::tss1,t2::tss2->ift1.rank<t2.rankthent1::merge_datatss1ts2elseift1.rank>t2.rankthent2::merge_datats1tss2elseadd_tree (linkt1t2)(merge_datatss1tss2)letmergebh1bh2=letsize=bh1.size+bh2.size inletdata=merge_databh1.data bh2.datainletmind=matchbh1.mind,bh2.mindwith|Some m1,Somem2->Some(ord_minm1m2)|m,None|None,m->min{size=size;data=data;mind=mind}let find_minbh=matchbh.mindwith|None->invalid_arg"find_min"|Somed->dletrecfind_min_treets~kfail~ksuccess=match tswith|[]->kfail()|[t]->ksuccesst|t::ts->find_min_treets~kfail~ksuccess:(funu->ifOrd.comparet.rootu.root<=0thenksuccesstelseksuccessu)letrecdel_min_treebts~kfail~ksuccess=match btswith|[]->kfail()|[t]->ksuccesst[]|t::ts->del_min_treets~kfail~ksuccess:(funuuts->ifOrd.comparet.rootu.root<=0thenksuccessttselseksuccessu(t::uts))letdel_minbh=letkfail()=invalid_arg"del_min"indel_min_tree bh.data~kfail~ksuccess:(funbtdata ->letsize=bh.size-1inletdata=merge_data(List.revbt.kids)datainletmind=ifsize=0thenNoneelseSome(find_min_treedata~kfail~ksuccess:(funt->t)).rootin{size;data;mind})let to_listbh=letrecauxaccbh=ifsize bh=0thenaccelseletm=find_minbhinletbh=del_minbhinaux(m::acc)bhinList.rev(aux[]bh)letelems =to_listletof_listl=List.fold_leftinsertemptyllet recenumbh=letcur=ref bhinletnext()=letbh=!curinifsizebh=0thenraiseBatEnum.No_more_elements;cur:=(del_minbh);find_min bhinletcount()=size!curinletclone()=enum!curinBatEnum.make~next~count~cloneletof_enume=BatEnum.foldinsertemptyeletprint?(first="[")?(last="]")?(sep="; ")elepr outbh=letrecspinbh =ifsizebh=0then()elseifsizebh=1theneleprout(find_minbh)elsebegineleprout(find_minbh);BatInnerIO.nwriteoutsep;spin (del_minbh)endinBatInnerIO.nwriteoutfirst;spinbh;BatInnerIO.nwriteoutlastend