
fj.data.PriorityQueue Maven / Gradle / Ivy
package fj.data;
import fj.Equal;
import fj.F;
import fj.F2;
import fj.Monoid;
import fj.Ord;
import fj.P;
import fj.P2;
import fj.Show;
import fj.data.fingertrees.FingerTree;
import static fj.Function.compose;
import static fj.data.Option.none;
import static fj.data.Option.some;
/**
* A priority queue implementation backed by a
* {@link fj.data.fingertrees.FingerTree}. The finger tree nodes are
* annotated with type K, are combined using a monoid of K and both the
* key and value are stored in the leaf. Priorities of the same value
* are returned FIFO (first in, first out).
*
* Created by MarkPerry on 31 May 16.
*/
public final class PriorityQueue {
private final FingerTree> ftree;
private final Equal equal;
private PriorityQueue(Equal e, FingerTree> ft) {
equal = e;
ftree = ft;
}
/**
* Creates a priority queue from a finger tree.
*/
public static PriorityQueue priorityQueue(Equal e, FingerTree> ft) {
return new PriorityQueue<>(e, ft);
}
/**
* Creates an empty priority queue.
*
* @param m A monoid to combine node annotations.
* @param e A value to compare key equality.
*/
public static PriorityQueue empty(Monoid m, Equal e) {
return priorityQueue(e, FingerTree.empty(m, P2.__1()));
}
/**
* An empty priority queue with integer priorities.
*/
public static PriorityQueue emptyInt() {
return empty(Monoid.intMaxMonoid, Equal.intEqual);
}
/**
* Maps the values in each node with function f.
*/
public PriorityQueue map(F f) {
return priorityQueue(equal,
ftree.map(P2.map2_(f),
FingerTree.measured(ftree.measured().monoid(), P2.__1())
)
);
}
/**
* Filters nodes based on the value inside each node.
*/
public PriorityQueue filterValues(F f) {
return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._2())));
}
/**
* Filters the nodes based on the annotation of each node.
*/
public PriorityQueue filterKeys(F f) {
return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._1())));
}
/**
* Is the tree empty?
*/
public boolean isEmpty() {
return ftree.isEmpty();
}
/**
* If the tree is not empty, returns the node with highest priority otherwise returns nothing.
*/
public Option> top() {
return unqueue(none(), (top, tail) -> some(top));
}
/**
* Returns all the elements of the queue with the highest (same) priority.
*/
public List> topN() {
return toStream().uncons(
List.nil(),
top -> tail -> List.cons(top, tail._1().takeWhile(compose(equal.eq(top._1()), P2.__1())).toList())
);
}
/**
* Adds a node with priority k and value a. This operation take O(1).
*/
public PriorityQueue enqueue(K k, A a) {
return priorityQueue(equal, ftree.snoc(P.p(k, a)));
}
/**
* Adds nodes using the list of products with priority k and value a. This operation takes O(list.length()).
*/
public PriorityQueue enqueue(List> list) {
return list.foldLeft((pq, p) -> pq.enqueue(p._1(), p._2()), this);
}
/**
* Does the priority k exist already?
*/
public boolean contains(final K k) {
return !ftree.split(equal.eq(k))._2().isEmpty();
}
/**
* Adds nodes using the iterable of products with priority k and value a.
*/
public PriorityQueue enqueue(Iterable> it) {
PriorityQueue result = this;
for (P2 p: it) {
result = result.enqueue(p);
}
return result;
}
/**
* Adds a node with priority k and value a. This operation take O(1).
*/
public PriorityQueue enqueue(P2 p) {
return enqueue(p._1(), p._2());
}
/**
* Removes the node with the highest priority.
*/
public PriorityQueue dequeue() {
return unqueue(this, (top, tail) -> tail);
}
/**
* Returns a tuple of the node with the highest priority and the rest of the priority queue.
*/
public P2
© 2015 - 2025 Weber Informatics LLC | Privacy Policy