123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Leftist Heaps} *)type'aiter=('a->unit)->unittype'agen=unit->'aoptiontype'aprinter=Format.formatter->'a->unittype'aktree=unit->[`Nil|`Nodeof'a*'aktreelist]moduletypePARTIAL_ORD=sigtypetvalleq:t->t->bool(** [leq x y] shall return [true] iff [x] is lower or equal to [y]. *)endmoduletypeTOTAL_ORD=sigtypetvalcompare:t->t->int(** [compare a b] shall return
a negative value if [a] is smaller than [b],
[0] if [a] and [b] are equal or
a positive value if [a] is greater than [b] *)endmoduletypeS=sigtypeelttypetvalempty:t(** Empty heap. *)valis_empty:t->bool(** Is the heap empty? *)exceptionEmptyvalmerge:t->t->t(** Merge two heaps. *)valinsert:elt->t->t(** Insert a value in the heap. *)valadd:t->elt->t(** Synonym to {!insert}. *)valfilter:(elt->bool)->t->t(** Filter values, only retaining the ones that satisfy the predicate.
Linear time at least. *)valfind_min:t->eltoption(** Find minimal element. *)valfind_min_exn:t->elt(** Like {!find_min} but can fail.
@raise Empty if the heap is empty. *)valtake:t->(t*elt)option(** Extract and return the minimum element, and the new heap (without
this element), or [None] if the heap is empty. *)valtake_exn:t->t*elt(** Like {!take}, but can fail.
@raise Empty if the heap is empty. *)valdelete_one:(elt->elt->bool)->elt->t->t(** Delete one occurrence of a value if it exist in the heap.
[delete_one eq x h], use [eq] to find one [x] in [h] and delete it.
If [h] do not contain [x] then it return [h].
@since 2.0 *)valdelete_all:(elt->elt->bool)->elt->t->t(** Delete all occurrences of a value in the heap.
[delete_all eq x h], use [eq] to find all [x] in [h] and delete them.
If [h] do not contain [x] then it return [h].
The difference with {!filter} is that [delete_all] stops as soon as
it enters a subtree whose root is bigger than the element.
@since 2.0 *)valiter:(elt->unit)->t->unit(** Iterate on elements. *)valfold:('a->elt->'a)->'a->t->'a(** Fold on all values. *)valsize:t->int(** Number of elements (linear complexity). *)(** {2 Conversions} *)valto_list:t->eltlist(** Return the elements of the heap, in no particular order. *)valto_list_sorted:t->eltlist(** Return the elements in increasing order.
@since 1.1 *)valadd_list:t->eltlist->t(** Add the elements of the list to the heap. An element occurring several
times will be added that many times to the heap.
@since 0.16 *)valof_list:eltlist->t(** [of_list l] is [add_list empty l]. Complexity: [O(n log n)]. *)valadd_iter:t->eltiter->t(** Like {!add_list}.
@since 2.8 *)valadd_seq:t->eltSeq.t->t(** Like {!add_list}.
@since 2.8 *)valof_iter:eltiter->t(** Build a heap from a given [iter]. Complexity: [O(n log n)].
@since 2.8 *)valof_seq:eltSeq.t->t(** Build a heap from a given [Seq.t]. Complexity: [O(n log n)].
@since 2.8 *)valto_iter:t->eltiter(** Return a [iter] of the elements of the heap.
@since 2.8 *)valto_seq:t->eltSeq.t(** Return a [Seq.t] of the elements of the heap.
@since 2.8 *)valto_iter_sorted:t->eltiter(** Iterate on the elements, in increasing order.
@since 2.8 *)valto_seq_sorted:t->eltSeq.t(** Iterate on the elements, in increasing order.
@since 2.8 *)valadd_gen:t->eltgen->t(** @since 0.16 *)valof_gen:eltgen->t(** Build a heap from a given [gen]. Complexity: [O(n log n)]. *)valto_gen:t->eltgen(** Return a [gen] of the elements of the heap. *)valto_tree:t->eltktree(** Return a [ktree] of the elements of the heap. *)valto_string:?sep:string->(elt->string)->t->string(** Print the heap in a string
@since 2.7 *)valpp:?pp_start:unitprinter->?pp_stop:unitprinter->?pp_sep:unitprinter->eltprinter->tprinter(** Printer.
Renamed from {!print} since 2.0
@since 0.16 *)endmoduleMake(E:PARTIAL_ORD):Swithtypeelt=E.t=structtypeelt=E.ttypet=E|Nofint*elt*t*tletempty=Eletis_empty=function|E->true|N_->falseexceptionEmpty(* Rank of the tree *)let_rank=function|E->0|N(r,_,_,_)->r(* Make a balanced node labelled with [x], and subtrees [a] and [b].
We ensure that the right child's rank is ≤ to the rank of the
left child (leftist property). The rank of the resulting node
is the length of the rightmost path. *)let_make_nodexab=if_ranka>=_rankbthenN(_rankb+1,x,a,b)elseN(_ranka+1,x,b,a)letrecmerget1t2=matcht1,t2with|t,E->t|E,t->t|N(_,x,a1,b1),N(_,y,a2,b2)->ifE.leqxythen_make_nodexa1(mergeb1t2)else_make_nodeya2(merget1b2)letinsertxh=merge(N(1,x,E,E))hletaddhx=insertxhletrecfilterph=matchhwith|E->E|N(_,x,l,r)whenpx->_make_nodex(filterpl)(filterpr)|N(_,_,l,r)->merge(filterpl)(filterpr)letfind_min_exn=function|E->raiseEmpty|N(_,x,_,_)->xletfind_min=function|E->None|N(_,x,_,_)->Somexlettake=function|E->None|N(_,x,l,r)->Some(mergelr,x)lettake_exn=function|E->raiseEmpty|N(_,x,l,r)->mergelr,xletdelete_oneeqxh=letrecaux=function|E->false,E|N(_,y,l,r)ash->ifeqxythentrue,mergelrelseifE.leqyxthen(letfound_left,l1=auxlinletfound,r1=iffound_leftthentrue,relseauxriniffoundthentrue,_make_nodeyl1r1elsefalse,h)elsefalse,hinsnd(auxh)letrecdelete_alleqx=function|E->E|N(_,y,l,r)ash->ifeqxythenmerge(delete_alleqxl)(delete_alleqxr)elseifE.leqyxthen_make_nodey(delete_alleqxl)(delete_alleqxr)elsehletreciterfh=matchhwith|E->()|N(_,x,l,r)->fx;iterfl;iterfrletrecfoldfacch=matchhwith|E->acc|N(_,x,a,b)->letacc=faccxinletacc=foldfaccainfoldfaccbletrecsize=function|E->0|N(_,_,l,r)->1+sizel+sizer(** {2 Conversions} *)letto_listh=letrecauxacch=matchhwith|E->acc|N(_,x,l,r)->x::aux(auxaccl)rinaux[]hletto_list_sortedheap=letrecrecurseacch=matchtakehwith|None->List.revacc|Some(h',x)->recurse(x::acc)h'inrecurse[]heapletadd_listhl=List.fold_leftaddhlletof_listl=add_listemptylletadd_iterhi=leth=refhini(funx->h:=insertx!h);!hletadd_seqhseq=leth=refhinSeq.iter(funx->h:=insertx!h)seq;!hletof_iteri=add_iteremptyiletof_seqseq=add_seqemptyseqletto_iterhk=iterkhletto_seqh=(* use an explicit stack [st] *)letrecauxst()=matchstwith|[]->Seq.Nil|E::st'->auxst'()|N(_,x,l,r)::st'->Seq.Cons(x,aux(l::r::st'))inaux[h]letto_iter_sortedheap=letrecrecursehk=matchtakehwith|None->()|Some(h',x)->kx;recurseh'kinfunk->recurseheapkletrecto_seq_sortedh()=matchtakehwith|None->Seq.Nil|Some(h',x)->Seq.Cons(x,to_seq_sortedh')letrecadd_genhg=matchg()with|None->h|Somex->add_gen(addhx)gletof_geng=add_genemptygletto_genh=letstack=Stack.create()inStack.pushhstack;letrecnext()=ifStack.is_emptystackthenNoneelse(matchStack.popstackwith|E->next()|N(_,x,a,b)->Stack.pushastack;Stack.pushbstack;Somex)innextletrecto_treeh()=matchhwith|E->`Nil|N(_,x,l,r)->`Node(x,[to_treel;to_treer])letto_string?(sep=",")elt_to_stringh=to_list_sortedh|>List.mapelt_to_string|>String.concatsepletpp?(pp_start=fun_()->())?(pp_stop=fun_()->())?(pp_sep=funout()->Format.fprintfout",")pp_eltouth=letfirst=reftrueinpp_startout();iter(funx->if!firstthenfirst:=falseelsepp_sepout();pp_eltoutx)h;pp_stopout()endmoduleMake_from_compare(E:TOTAL_ORD)=Make(structtypet=E.tletleqab=E.compareab<=0end)