22
33import fj .Equal ;
44import fj .F ;
5+ import fj .F2 ;
56import fj .Monoid ;
67import fj .Ord ;
78import fj .P ;
89import fj .P2 ;
9- import fj .P3 ;
1010import fj .Show ;
1111import fj .data .fingertrees .FingerTree ;
1212
13- import static fj .data .List .list ;
13+ import static fj .Function .compose ;
14+ import static fj .data .Option .none ;
15+ import static fj .data .Option .some ;
1416
1517/**
1618 * A priority queue implementation backed by a
@@ -91,22 +93,17 @@ public boolean isEmpty() {
9193 * If the tree is not empty, returns the node with highest priority otherwise returns nothing.
9294 */
9395 public Option <P2 <K , A >> top () {
94- K top = ftree .measure ();
95- P2 <FingerTree <K , P2 <K , A >>, FingerTree <K , P2 <K , A >>> p = ftree .split (k -> equal .eq (top , k ));
96- return p ._2 ().headOption ();
96+ return unqueue (none (), (top , tail ) -> some (top ));
9797 }
9898
9999 /**
100100 * Returns all the elements of the queue with the highest (same) priority.
101101 */
102102 public List <P2 <K , A >> topN () {
103- Stream <P2 <K , A >> s = toStream ();
104- if (s .isEmpty ()) {
105- return List .nil ();
106- } else {
107- final K k = s .head ()._1 ();
108- return s .takeWhile (p -> equal .eq (k , p ._1 ())).toList ();
109- }
103+ return toStream ().uncons (
104+ List .nil (),
105+ top -> tail -> List .cons (top , tail ._1 ().takeWhile (compose (equal .eq (top ._1 ()), P2 .__1 ())).toList ())
106+ );
110107 }
111108
112109 /**
@@ -127,7 +124,7 @@ public PriorityQueue<K, A> enqueue(List<P2<K, A>> list) {
127124 * Does the priority k exist already?
128125 */
129126 public boolean contains (final K k ) {
130- return !ftree .split (k2 -> equal .eq (k , k2 ))._2 ().isEmpty ();
127+ return !ftree .split (equal .eq (k ))._2 ().isEmpty ();
131128 }
132129
133130 /**
@@ -152,17 +149,30 @@ public PriorityQueue<K, A> enqueue(P2<K, A> p) {
152149 * Removes the node with the highest priority.
153150 */
154151 public PriorityQueue <K , A > dequeue () {
155- K top = ftree .measure ();
156- P2 <FingerTree <K , P2 <K , A >>, FingerTree <K , P2 <K , A >>> p = ftree .split (k -> equal .eq (k , top ));
157- FingerTree <K , P2 <K , A >> right = p ._2 ();
158- return right .isEmpty () ? this : priorityQueue (equal , p ._1 ().append (right .tail ()));
152+ return unqueue (this , (top , tail ) -> tail );
159153 }
160154
161155 /**
162156 * Returns a tuple of the node with the highest priority and the rest of the priority queue.
163157 */
164158 public P2 <Option <P2 <K , A >>, PriorityQueue <K , A >> topDequeue () {
165- return P .p (top (), dequeue ());
159+ return unqueue (P .p (none (), this ), (top , tail ) -> P .p (some (top ), tail ));
160+ }
161+
162+ /**
163+ * Performs a reduction on this priority queue using the given arguments.
164+ *
165+ * @param empty The value to return if this queue is empty.
166+ * @param topDequeue The function to apply to the top priority element and the tail of the queue (without its top element).
167+ * @return A reduction on this queue.
168+ */
169+ public <B > B unqueue (B empty , F2 <P2 <K , A >, PriorityQueue <K , A >, B > topDequeue ) {
170+ K top = ftree .measure ();
171+ P2 <FingerTree <K , P2 <K , A >>, FingerTree <K , P2 <K , A >>> p = ftree .split (equal .eq (top ));
172+ return p ._2 ().uncons (
173+ empty ,
174+ (head , tail ) -> topDequeue .f (head , priorityQueue (equal , p ._1 ().append (tail )))
175+ );
166176 }
167177
168178 /**
@@ -182,22 +192,22 @@ public PriorityQueue<K, A> dequeue(int n) {
182192 * Does the top of the queue have lower priority than k?
183193 */
184194 public boolean isLessThan (Ord <K > ok , K k ) {
185- return top ().map ( p -> ok .isLessThan (p ._1 (), k )). orSome ( true );
195+ return top ().option ( true , p -> ok .isLessThan (p ._1 (), k ));
186196 }
187197
188198 public boolean isGreaterThan (Ord <K > ok , K k ) {
189- return top ().map ( p -> ok .isGreaterThan (p ._1 (), k )). orSome ( false );
199+ return top ().option ( false , p -> ok .isGreaterThan (p ._1 (), k ));
190200 }
191201
192202 public boolean isEqual (Ord <K > ok , K k ) {
193- return top ().map ( p -> ok .eq (p ._1 (), k )). orSome ( false );
203+ return top ().option ( false , p -> ok .eq (p ._1 (), k ));
194204 }
195205
196206 /**
197207 * Returns a stream of products with priority k and value a.
198208 */
199209 public Stream <P2 <K , A >> toStream () {
200- return top (). map ( p -> Stream .cons (p , () -> dequeue () .toStream ())). orSome (() -> Stream . nil ( ));
210+ return unqueue ( Stream . nil (), ( top , tail ) -> Stream .cons (top , () -> tail .toStream ()));
201211 }
202212
203213 /**
0 commit comments