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.rootinletroot=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(linktut)utsletinsertbhx=letsize=bh.size+1inletdata=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->ift1.rank<t2.rankthent1::merge_datatss1ts2elseift1.rank>t2.rankthent2::merge_datats1tss2elseadd_tree(linkt1t2)(merge_datatss1tss2)letmergebh1bh2=letsize=bh1.size+bh2.sizeinletdata=merge_databh1.databh2.datainletmind=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_minbh=letkfail()=invalid_arg"del_min"indel_min_treebh.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_minbhinletbh=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="; ")eleproutbh=letrecspinbh=ifsizebh=0then()elseifsizebh=1theneleprout(find_minbh)elsebegineleprout(find_minbh);BatInnerIO.nwriteoutsep;spin(del_minbh)endinBatInnerIO.nwriteoutfirst;spinbh;BatInnerIO.nwriteoutlastletrecenumbh=letcur=refbhinletnext()=letbh=!curinifsizebh=0thenraiseBatEnum.No_more_elements;cur:=(del_minbh);find_minbhinletcount()=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:elemlist->tvalto_list:t->elemlistvalelems:t->elemlistvalof_enum:elemBatEnum.t->tvalenum:t->elemBatEnum.tvalprint:?first:string->?last:string->?sep:string->('aBatInnerIO.output->elem->unit)->'aBatInnerIO.output->t->unitendmoduleMake(Ord:BatInterfaces.OrderedType)=structtypeelem=Ord.tletord_minxy=ifOrd.comparexy<=0thenxelseytypebt={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.rootbt2.root<=0inletroot=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(linktut)utsletinsertbhx=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.sizeinletdata=merge_databh1.databh2.datainletmind=matchbh1.mind,bh2.mindwith|Somem1,Somem2->Some(ord_minm1m2)|m,None|None,m->min{size=size;data=data;mind=mind}letfind_minbh=matchbh.mindwith|None->invalid_arg"find_min"|Somed->dletrecfind_min_treets~kfail~ksuccess=matchtswith|[]->kfail()|[t]->ksuccesst|t::ts->find_min_treets~kfail~ksuccess:(funu->ifOrd.comparet.rootu.root<=0thenksuccesstelseksuccessu)letrecdel_min_treebts~kfail~ksuccess=matchbtswith|[]->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_treebh.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})letto_listbh=letrecauxaccbh=ifsizebh=0thenaccelseletm=find_minbhinletbh=del_minbhinaux(m::acc)bhinList.rev(aux[]bh)letelems=to_listletof_listl=List.fold_leftinsertemptylletrecenumbh=letcur=refbhinletnext()=letbh=!curinifsizebh=0thenraiseBatEnum.No_more_elements;cur:=(del_minbh);find_minbhinletcount()=size!curinletclone()=enum!curinBatEnum.make~next~count~cloneletof_enume=BatEnum.foldinsertemptyeletprint?(first="[")?(last="]")?(sep="; ")eleproutbh=letrecspinbh=ifsizebh=0then()elseifsizebh=1theneleprout(find_minbh)elsebegineleprout(find_minbh);BatInnerIO.nwriteoutsep;spin(del_minbh)endinBatInnerIO.nwriteoutfirst;spinbh;BatInnerIO.nwriteoutlastend