123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108(******************************************************************************)(* *)(* Menhir *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under *)(* the terms of the GNU Library General Public License version 2, with a *)(* special exception on linking, as described in the file LICENSE. *)(* *)(******************************************************************************)(* This code is borrowed from Jean-Christophe Filliâtre, author of the PQueue
module in OCaml's standard library, version 5.3. *)(* A priority queue is implemented as a "min heap" data structure, that is, as
a binary tree, stored inside a vector. *)module[@inline]Make(E:sigtypetvalcompare:t->t->intend)(V:sigtype'avectorvalcreate:unit->'avectorvallength:'avector->intvalget:'avector->int->'avalset:'avector->int->'a->unitvalpush:'avector->'a->unitvalpop:'avector->'aend)=structtypeelement=E.ttypequeue=elementV.vectortypet=queueletcreate=V.createletis_emptyh=V.lengthh=0(* The node at index [i] has children nodes at indices [2 * i + 1] and
[2 * i + 2] -- provided these are valid indices into the vector. *)let[@inline]left_childi=2*i+1let[@inline]right_childi=2*i+2let[@inline]parent_nodei=(i-1)/2(* A heap respects the "heap ordering" if the value of each node is no greater
than the value of its children. The algorithm manipulates arrays that
respect the heap ordering, except for one node whose value may be too small
or too large. The auxiliary functions [sift_up] and [sift_down] move such a
misplaced value "up" or "down" until the heap ordering is restored. *)(* [sift_up h i x] stores [x] at index [i], moving it up if necessary. *)letrecsift_uphix=ifi=0thenV.seth0xelseletp=parent_nodeiinlety=V.gethpinifE.comparexy<0then(V.sethiy;sift_uphpx)elseV.sethixletaddhx=leti=V.lengthhinV.pushhx;ifi>0thensift_uphixexceptionEmpty(* [sift_down h ~len i x] stores [x] at index [i],
moving it down if necessary.
[len] is the length of the vector. *)letrecsift_downh~lenix=letleft=left_childiinifleft>=lenthenV.sethix(* no child, stop *)elseletsmallest=letright=right_childiinifright>=lenthenleft(* no right child *)elseifE.compare(V.gethleft)(V.gethright)<0thenleftelserightinlety=V.gethsmallestinifE.compareyx<0then(V.sethiy;sift_downh~lensmallestx)elseV.sethixletextracth=letn=V.lengthhinifn=0thenNoneelseletx=V.pophinifn=1thenSomexelseletr=V.geth0insift_downh~len:(n-1)0x;Somerend