diff --git a/src/main/java/com/github/btrekkie/connectivity/Augmentation.java b/src/main/java/com/github/btrekkie/connectivity/Augmentation.java
index 1d2a443c8..4c9a4f8d7 100644
--- a/src/main/java/com/github/btrekkie/connectivity/Augmentation.java
+++ b/src/main/java/com/github/btrekkie/connectivity/Augmentation.java
@@ -7,7 +7,7 @@ package com.github.btrekkie.connectivity;
* combine(combine(combine(A1, A2), A3), A4). In order for an augmentation result to be meaningful, the combining
* function must be commutative, meaning combine(x, y) is equivalent to combine(y, x), and associative, meaning
* combine(x, combine(y, z)) is equivalent to combine(combine(x, y), z).
- *
+ *
* If a ConnGraph represents a game map, then one example of an augmentation would be the amount of gold accessible from
* a certain location. Each vertex would be augmented with the amount of gold in that location, and the combining
* function would add the two amounts of gold passed in as arguments. Another example would be the strongest monster
@@ -16,18 +16,18 @@ package com.github.btrekkie.connectivity;
* in as arguments. A third example would be the number of locations accessible from a given vertex. Each vertex would
* be augmented with the number 1, and the combining function would add the two numbers of vertices passed in as
* arguments.
- *
+ *
* ConnGraph treats two augmentation values X and Y as interchangeable if they are equal, as in
* X != null ? X.equals(Y) : Y == null. The same holds for two combined augmentation values, and for one combined
* augmentation value and one augmentation value.
- *
+ *
* See the comments for ConnGraph.
*/
public interface Augmentation {
/**
* Returns the result of combining the specified values into one. Each argument is either the augmentation
* information associated with a vertex, or the result of a previous call to "combine".
- *
+ *
* Note that a value of null is never passed in to indicate the absence of augmentation information. The fact that
* ConnGraph.getVertexAugmentation, for example, may return null when there is no associated augmentation might lead
* you to believe that a null argument indicates the absence of augmentation information, but again, it does not. A
diff --git a/src/main/java/com/github/btrekkie/connectivity/ConnEdge.java b/src/main/java/com/github/btrekkie/connectivity/ConnEdge.java
index 691aa6ed7..1b8ed65e3 100644
--- a/src/main/java/com/github/btrekkie/connectivity/ConnEdge.java
+++ b/src/main/java/com/github/btrekkie/connectivity/ConnEdge.java
@@ -4,7 +4,7 @@ package com.github.btrekkie.connectivity;
* Represents an edge in a ConnGraph, at the level of the edge (i.e. at the lowest level i for which G_i contains the
* edge). Every graph edge has exactly one corresponding ConnEdge object, regardless of the number of levels it appears
* in. See the comments for the implementation of ConnGraph.
- *
+ *
* ConnEdges are stored in the linked lists suggested by EulerTourVertex.graphListHead and
* EulerTourVertex.forestListHead. Each ConnEdge is in two linked lists, so care must be taken when traversing the
* linked lists. prev1 and next1 are the links for the list starting at vertex1.graphListHead or vertex1.forestListHead,
@@ -14,10 +14,14 @@ package com.github.btrekkie.connectivity;
* after next1 is next1.next1, but otherwise, it is next1.next2.
*/
class ConnEdge {
- /** The edge's first endpoint (at the same level as the edge). */
+ /**
+ * The edge's first endpoint (at the same level as the edge).
+ */
public EulerTourVertex vertex1;
- /** The edge's second endpoint (at the same level as the edge). */
+ /**
+ * The edge's second endpoint (at the same level as the edge).
+ */
public EulerTourVertex vertex2;
/**
diff --git a/src/main/java/com/github/btrekkie/connectivity/ConnGraph.java b/src/main/java/com/github/btrekkie/connectivity/ConnGraph.java
index 545760892..793eef0fd 100644
--- a/src/main/java/com/github/btrekkie/connectivity/ConnGraph.java
+++ b/src/main/java/com/github/btrekkie/connectivity/ConnGraph.java
@@ -1,10 +1,6 @@
package com.github.btrekkie.connectivity;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
/**
* Implements an undirected graph with dynamic connectivity. It supports adding and removing edges and determining
@@ -12,7 +8,7 @@ import java.util.Map;
* amortized time with high probability, while checking whether two vertices are connected takes O(log N) time with high
* probability. It uses O(V log V + E) space, where V is the number of vertices and E is the number of edges. Note that
* a ConnVertex may appear in multiple ConnGraphs, with a different set of adjacent vertices in each graph.
- *
+ *
* ConnGraph optionally supports arbitrary augmentation. Each vertex may have an associated augmentation, or value.
* Given a vertex V, ConnGraph can quickly report the result of combining the augmentations of all of the vertices in
* the connected component containing V, using a combining function provided to the constructor. For example, if a
@@ -22,12 +18,12 @@ import java.util.Map;
* the augmentation takes a constant amount of space. Retrieving the combined augmentation for a connected component
* takes O(log N) time with high probability. (Although ConnGraph does not directly support augmenting edges, this can
* also be accomplished, by imputing each edge's augmentation to an adjacent vertex.)
- *
+ *
* When a vertex no longer has any adjacent edges, and it has no augmentation information, ConnGraph stops keeping track
* of the vertex. This reduces the time and space bounds of the ConnGraph, and it enables the ConnVertex to be garbage
* collected. If you know you are finished with a vertex, and that vertex has an augmentation, then you should call
* removeVertexAugmentation on the vertex, so that the graph can release it.
- *
+ *
* As a side note, it would be more proper if ConnGraph had a generic type parameter indicating the type of the
* augmentation values. However, it is expected that it is more common not to use augmentation, so by not using a type
* parameter, we make usage of the ConnGraph class more convenient and less confusing in the common case.
@@ -106,7 +102,7 @@ public class ConnGraph {
* The maximum number of vertices we can store in a ConnGraph. This is limited by the fact that EulerTourNode.size
* is an int. Since the size of an Euler tour tree is one less than twice the number of vertices in the tree, the
* number of vertices may be at most (int)((((long)Integer.MAX_VALUE) + 1) / 2).
- *
+ *
* Of course, we could simply change the "size" field to be a long. But more fundamentally, the number of vertices
* is limited by the fact that vertexInfo and VertexInfo.edges use HashMaps. Using a HashMap becomes problematic at
* around Integer.MAX_VALUE entries. HashMap buckets entries based on 32-bit hash codes, so in principle, it can
@@ -115,7 +111,9 @@ public class ConnGraph {
*/
private static final int MAX_VERTEX_COUNT = 1 << 30;
- /** The augmentation function for the graph, if any. */
+ /**
+ * The augmentation function for the graph, if any.
+ */
private final Augmentation augmentation;
/**
@@ -139,22 +137,28 @@ public class ConnGraph {
*/
private int maxVertexInfoSize;
- /** Constructs a new ConnGraph with no augmentation. */
+ /**
+ * Constructs a new ConnGraph with no augmentation.
+ */
public ConnGraph() {
augmentation = null;
}
- /** Constructs an augmented ConnGraph, using the specified function to combine augmentation values. */
+ /**
+ * Constructs an augmented ConnGraph, using the specified function to combine augmentation values.
+ */
public ConnGraph(Augmentation augmentation) {
this.augmentation = augmentation;
}
- /** Equivalent implementation is contractual. */
+ /**
+ * Equivalent implementation is contractual.
+ */
private void assertIsAugmented() {
if (augmentation == null) {
throw new RuntimeException(
- "You may only call augmentation-related methods on ConnGraph if the graph is augmented, i.e. if an " +
- "Augmentation was passed to the constructor");
+ "You may only call augmentation-related methods on ConnGraph if the graph is augmented, i.e. if an " +
+ "Augmentation was passed to the constructor");
}
}
@@ -171,8 +175,8 @@ public class ConnGraph {
if (vertexInfo.size() == MAX_VERTEX_COUNT) {
throw new RuntimeException(
- "Sorry, ConnGraph has too many vertices to perform this operation. ConnGraph does not support " +
- "storing more than ~2^30 vertices at a time.");
+ "Sorry, ConnGraph has too many vertices to perform this operation. ConnGraph does not support " +
+ "storing more than ~2^30 vertices at a time.");
}
EulerTourVertex eulerTourVertex = new EulerTourVertex();
@@ -215,9 +219,10 @@ public class ConnGraph {
* list for an EulerTourVertex that represents the same underlying ConnVertex, but at a higher level. This has the
* effect of prepending the list for the lower level to the beginning of the list for the higher level, and
* replacing all links to the lower-level vertex in the ConnEdges with links to the higher-level vertex.
- * @param head The first node in the list for the higher-level vertex.
- * @param lowerHead The first node in the list for the lower-level vertex.
- * @param vertex The higher-level vertex.
+ *
+ * @param head The first node in the list for the higher-level vertex.
+ * @param lowerHead The first node in the list for the lower-level vertex.
+ * @param vertex The higher-level vertex.
* @param lowerVertex The lower-level vertex.
* @return The head of the combined linked list.
*/
@@ -257,7 +262,7 @@ public class ConnGraph {
/**
* Equivalent implementation is contractual.
- *
+ *
* This method is useful for when an EulerTourVertex's lists (graphListHead or forestListHead) or arbitrary visit
* change, as these affect the hasGraphEdge and hasForestEdge augmentations.
*/
@@ -301,7 +306,7 @@ public class ConnGraph {
}
vertex.graphListHead =
- collapseEdgeList(vertex.graphListHead, lowerVertex.graphListHead, vertex, lowerVertex);
+ collapseEdgeList(vertex.graphListHead, lowerVertex.graphListHead, vertex, lowerVertex);
if (lowerVertex.forestListHead != null) {
// Change the eulerTourEdge links
ConnEdge lowerEdge = lowerVertex.forestListHead;
@@ -320,7 +325,7 @@ public class ConnGraph {
}
vertex.forestListHead =
- collapseEdgeList(vertex.forestListHead, lowerVertex.forestListHead, vertex, lowerVertex);
+ collapseEdgeList(vertex.forestListHead, lowerVertex.forestListHead, vertex, lowerVertex);
}
}
@@ -505,7 +510,9 @@ public class ConnGraph {
return new EulerTourEdge(newNode, max);
}
- /** Removes the specified edge from the Euler tour forest F_i. */
+ /**
+ * Removes the specified edge from the Euler tour forest F_i.
+ */
private void removeForestEdge(EulerTourEdge edge) {
EulerTourNode firstNode;
EulerTourNode secondNode;
@@ -535,8 +542,9 @@ public class ConnGraph {
/**
* Adds the specified edge to the edge map for srcInfo (srcInfo.edges). Assumes that the edge is not currently in
* the map.
- * @param edge The edge.
- * @param srcInfo The source vertex's info.
+ *
+ * @param edge The edge.
+ * @param srcInfo The source vertex's info.
* @param destVertex The destination vertex, i.e. the edge's key in srcInfo.edges.
*/
private void addToEdgeMap(ConnEdge edge, VertexInfo srcInfo, ConnVertex destVertex) {
@@ -549,6 +557,7 @@ public class ConnGraph {
/**
* Adds an edge between the specified vertices, if such an edge is not already present. Taken together with
* removeEdge, this method takes O(log^2 N) amortized time with high probability.
+ *
* @return Whether there was no edge between the vertices.
*/
public boolean addEdge(ConnVertex connVertex1, ConnVertex connVertex2) {
@@ -557,8 +566,8 @@ public class ConnGraph {
}
if (vertexInfo.size() >= MAX_VERTEX_COUNT - 1) {
throw new RuntimeException(
- "Sorry, ConnGraph has too many vertices to perform this operation. ConnGraph does not support " +
- "storing more than ~2^30 vertices at a time.");
+ "Sorry, ConnGraph has too many vertices to perform this operation. ConnGraph does not support " +
+ "storing more than ~2^30 vertices at a time.");
}
VertexInfo info1 = ensureInfo(connVertex1);
if (info1.edges.containsKey(connVertex2)) {
@@ -614,7 +623,7 @@ public class ConnGraph {
return;
}
EulerTourNode node;
- for (node = root; node.left.hasForestEdge; node = node.left);
+ for (node = root; node.left.hasForestEdge; node = node.left) ;
while (node != null) {
EulerTourVertex vertex = node.vertex;
ConnEdge edge = vertex.forestListHead;
@@ -657,7 +666,7 @@ public class ConnGraph {
// Iterate to the next node with hasForestEdge == true, clearing hasForestEdge as we go
if (node.right.hasForestEdge) {
- for (node = node.right; node.left.hasForestEdge; node = node.left);
+ for (node = node.right; node.left.hasForestEdge; node = node.left) ;
} else {
node.hasForestEdge = false;
while (node.parent != null && node.parent.right == node) {
@@ -674,6 +683,7 @@ public class ConnGraph {
* tree, where i is the level of the tree. This is a "replacement" edge because it replaces the edge that was
* previously connecting the two trees. We push any level-i edges we encounter that do not connect to another tree
* down to level i - 1, adding them to G_{i - 1}. This method assumes that root.hasForestEdge is false.
+ *
* @param root The root of the tree.
* @return The replacement edge, or null if there is no replacement edge.
*/
@@ -683,7 +693,7 @@ public class ConnGraph {
return null;
}
EulerTourNode node;
- for (node = root; node.left.hasGraphEdge; node = node.left);
+ for (node = root; node.left.hasGraphEdge; node = node.left) ;
while (node != null) {
EulerTourVertex vertex = node.vertex;
ConnEdge edge = vertex.graphListHead;
@@ -767,7 +777,7 @@ public class ConnGraph {
// Iterate to the next node with hasGraphEdge == true. Note that nodes' hasGraphEdge fields can change as we
// push down edges.
if (node.right.hasGraphEdge) {
- for (node = node.right; node.left.hasGraphEdge; node = node.left);
+ for (node = node.right; node.left.hasGraphEdge; node = node.left) ;
} else {
while (node.parent != null && (node.parent.right == node || !node.parent.hasGraphEdge)) {
node = node.parent;
@@ -798,6 +808,7 @@ public class ConnGraph {
/**
* Removes the edge between the specified vertices, if there is such an edge. Taken together with addEdge, this
* method takes O(log^2 N) amortized time with high probability.
+ *
* @return Whether there was an edge between the vertices.
*/
public boolean removeEdge(ConnVertex vertex1, ConnVertex vertex2) {
@@ -912,7 +923,9 @@ public class ConnGraph {
return info2 != null && info1.vertex.arbitraryVisit.root() == info2.vertex.arbitraryVisit.root();
}
- /** Returns the vertices that are directly adjacent to the specified vertex. */
+ /**
+ * Returns the vertices that are directly adjacent to the specified vertex.
+ */
public Collection adjacentVertices(ConnVertex vertex) {
VertexInfo info = vertexInfo.get(vertex);
if (info != null) {
@@ -925,12 +938,12 @@ public class ConnGraph {
/**
* Sets the augmentation associated with the specified vertex. This method takes O(log N) time with high
* probability.
- *
+ *
* Note that passing a null value for the second argument is not the same as removing the augmentation. For that,
* you need to call removeVertexAugmentation.
*
* @return The augmentation that was previously associated with the vertex. Returns null if it did not have any
- * associated augmentation.
+ * associated augmentation.
*/
public Object setVertexAugmentation(ConnVertex connVertex, Object vertexAugmentation) {
assertIsAugmented();
@@ -952,8 +965,9 @@ public class ConnGraph {
/**
* Removes any augmentation associated with the specified vertex. This method takes O(log N) time with high
* probability.
+ *
* @return The augmentation that was previously associated with the vertex. Returns null if it did not have any
- * associated augmentation.
+ * associated augmentation.
*/
public Object removeVertexAugmentation(ConnVertex connVertex) {
assertIsAugmented();
@@ -1127,7 +1141,7 @@ public class ConnGraph {
private void optimizeGraphEdges() {
for (VertexInfo info : vertexInfo.values()) {
EulerTourVertex vertex;
- for (vertex = info.vertex; vertex.lowerVertex != null; vertex = vertex.lowerVertex);
+ for (vertex = info.vertex; vertex.lowerVertex != null; vertex = vertex.lowerVertex) ;
while (vertex != null) {
EulerTourNode node = vertex.arbitraryVisit;
ConnEdge edge = vertex.graphListHead;
diff --git a/src/main/java/com/github/btrekkie/connectivity/ConnVertex.java b/src/main/java/com/github/btrekkie/connectivity/ConnVertex.java
index 41d30c836..49e55413a 100644
--- a/src/main/java/com/github/btrekkie/connectivity/ConnVertex.java
+++ b/src/main/java/com/github/btrekkie/connectivity/ConnVertex.java
@@ -2,9 +2,13 @@ package com.github.btrekkie.connectivity;
import java.util.Random;
-/** A vertex in a ConnGraph. See the comments for ConnGraph. */
+/**
+ * A vertex in a ConnGraph. See the comments for ConnGraph.
+ */
public class ConnVertex {
- /** The thread-local random number generator we use by default to set the "hash" field. */
+ /**
+ * The thread-local random number generator we use by default to set the "hash" field.
+ */
private static final ThreadLocal random = new ThreadLocal() {
@Override
protected Random initialValue() {
@@ -24,8 +28,9 @@ public class ConnVertex {
/**
* Constructs a new ConnVertex.
+ *
* @param random The random number generator to use to produce a random hash code. ConnGraph relies on random hash
- * codes for its performance guarantees.
+ * codes for its performance guarantees.
*/
public ConnVertex(Random random) {
hash = random.nextInt();
diff --git a/src/main/java/com/github/btrekkie/connectivity/EulerTourNode.java b/src/main/java/com/github/btrekkie/connectivity/EulerTourNode.java
index 9d1f068f9..356f98733 100644
--- a/src/main/java/com/github/btrekkie/connectivity/EulerTourNode.java
+++ b/src/main/java/com/github/btrekkie/connectivity/EulerTourNode.java
@@ -7,13 +7,19 @@ import com.github.btrekkie.red_black_node.RedBlackNode;
* ConnGraph.
*/
class EulerTourNode extends RedBlackNode {
- /** The dummy leaf node. */
+ /**
+ * The dummy leaf node.
+ */
public static final EulerTourNode LEAF = new EulerTourNode(null, null);
- /** The vertex this node visits. */
+ /**
+ * The vertex this node visits.
+ */
public final EulerTourVertex vertex;
- /** The number of nodes in the subtree rooted at this node. */
+ /**
+ * The number of nodes in the subtree rooted at this node.
+ */
public int size;
/**
@@ -53,13 +59,15 @@ class EulerTourNode extends RedBlackNode {
this.augmentationFunc = augmentationFunc;
}
- /** Like augment(), but only updates the augmentation fields hasGraphEdge and hasForestEdge. */
+ /**
+ * Like augment(), but only updates the augmentation fields hasGraphEdge and hasForestEdge.
+ */
public boolean augmentFlags() {
boolean newHasGraphEdge =
- left.hasGraphEdge || right.hasGraphEdge || (vertex.arbitraryVisit == this && vertex.graphListHead != null);
+ left.hasGraphEdge || right.hasGraphEdge || (vertex.arbitraryVisit == this && vertex.graphListHead != null);
boolean newHasForestEdge =
- left.hasForestEdge || right.hasForestEdge ||
- (vertex.arbitraryVisit == this && vertex.forestListHead != null);
+ left.hasForestEdge || right.hasForestEdge ||
+ (vertex.arbitraryVisit == this && vertex.forestListHead != null);
if (newHasGraphEdge == hasGraphEdge && newHasForestEdge == hasForestEdge) {
return false;
} else {
diff --git a/src/main/java/com/github/btrekkie/connectivity/EulerTourVertex.java b/src/main/java/com/github/btrekkie/connectivity/EulerTourVertex.java
index 2b02940b0..e2412e189 100644
--- a/src/main/java/com/github/btrekkie/connectivity/EulerTourVertex.java
+++ b/src/main/java/com/github/btrekkie/connectivity/EulerTourVertex.java
@@ -35,9 +35,13 @@ class EulerTourVertex {
*/
public ConnEdge forestListHead;
- /** The augmentation associated with this vertex, if any. This is null instead if higherVertex != null. */
+ /**
+ * The augmentation associated with this vertex, if any. This is null instead if higherVertex != null.
+ */
public Object augmentation;
- /** Whether there is any augmentation associated with this vertex. This is false instead if higherVertex != null. */
+ /**
+ * Whether there is any augmentation associated with this vertex. This is false instead if higherVertex != null.
+ */
public boolean hasAugmentation;
}
diff --git a/src/main/java/com/github/btrekkie/connectivity/VertexInfo.java b/src/main/java/com/github/btrekkie/connectivity/VertexInfo.java
index 1593a2040..19c172ed1 100644
--- a/src/main/java/com/github/btrekkie/connectivity/VertexInfo.java
+++ b/src/main/java/com/github/btrekkie/connectivity/VertexInfo.java
@@ -8,7 +8,9 @@ import java.util.Map;
* a given graph, regardless of how many levels the vertex is in. See the comments for the implementation of ConnGraph.
*/
class VertexInfo {
- /** The representation of the vertex in the highest level. */
+ /**
+ * The representation of the vertex in the highest level.
+ */
public EulerTourVertex vertex;
/**
diff --git a/src/main/java/com/github/btrekkie/red_black_node/RedBlackNode.java b/src/main/java/com/github/btrekkie/red_black_node/RedBlackNode.java
index 51cf7c5c0..1484562cd 100644
--- a/src/main/java/com/github/btrekkie/red_black_node/RedBlackNode.java
+++ b/src/main/java/com/github/btrekkie/red_black_node/RedBlackNode.java
@@ -3,11 +3,7 @@
package com.github.btrekkie.red_black_node;
import java.lang.reflect.Array;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+import java.util.*;
/**
* A node in a red-black tree ( https://en.wikipedia.org/wiki/Red%E2%80%93black_tree ). Compared to a class like Java's
@@ -15,20 +11,20 @@ import java.util.Set;
* clients to directly observe and manipulate the structure of the tree. This gives clients flexibility, although it
* also enables them to violate the red-black or BST properties. The RedBlackNode class provides methods for performing
* various standard operations, such as insertion and removal.
- *
+ *
* Unlike most implementations of binary search trees, RedBlackNode supports arbitrary augmentation. By subclassing
* RedBlackNode, clients can add arbitrary data and augmentation information to each node. For example, if we were to
* use a RedBlackNode subclass to implement a sorted set, the subclass would have a field storing an element in the set.
* If we wanted to keep track of the number of non-leaf nodes in each subtree, we would store this as a "size" field and
* override augment() to update this field. All RedBlackNode methods (such as "insert" and remove()) call augment() as
* necessary to correctly maintain the augmentation information, unless otherwise indicated.
- *
+ *
* The values of the tree are stored in the non-leaf nodes. RedBlackNode does not support use cases where values must be
* stored in the leaf nodes. It is recommended that all of the leaf nodes in a given tree be the same (black)
* RedBlackNode instance, to save space. The root of an empty tree is a leaf node, as opposed to null.
- *
+ *
* For reference, a red-black tree is a binary search tree satisfying the following properties:
- *
+ *
* - Every node is colored red or black.
* - The leaf nodes, which are dummy nodes that do not store any values, are colored black.
* - The root is black.
@@ -36,11 +32,13 @@ import java.util.Set;
* - Every path from the root to a leaf contains the same number of black nodes.
*
* @param The type of node in the tree. For example, we might have
- * "class FooNode extends RedBlackNode>".
+ * "class FooNode extends RedBlackNode>".
* @author Bill Jacobs
*/
public abstract class RedBlackNode> implements Comparable {
- /** A Comparator that compares Comparable elements using their natural order. */
+ /**
+ * A Comparator that compares Comparable elements using their natural order.
+ */
private static final Comparator> NATURAL_ORDER = new Comparator>() {
@Override
public int compare(Comparable