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 value1, Comparable value2) { @@ -48,16 +46,24 @@ public abstract class RedBlackNode> implements Compara } }; - /** The parent of this node, if any. "parent" is null if this is a leaf node. */ + /** + * The parent of this node, if any. "parent" is null if this is a leaf node. + */ public N parent; - /** The left child of this node. "left" is null if this is a leaf node. */ + /** + * The left child of this node. "left" is null if this is a leaf node. + */ public N left; - /** The right child of this node. "right" is null if this is a leaf node. */ + /** + * The right child of this node. "right" is null if this is a leaf node. + */ public N right; - /** Whether the node is colored red, as opposed to black. */ + /** + * Whether the node is colored red, as opposed to black. + */ public boolean isRed; /** @@ -65,12 +71,12 @@ public abstract class RedBlackNode> implements Compara * example, if we augment each node by subtree size (the number of non-leaf nodes in the subtree), this method would * set the size field of this node to be equal to the size field of the left child plus the size field of the right * child plus one. - * + *

* "Augmentation information" is information that we can compute about a subtree rooted at some node, preferably * based only on the augmentation information in the node's two children and the information in the node. Examples * of augmentation information are the sum of the values in a subtree and the number of non-leaf nodes in a subtree. * Augmentation information may not depend on the colors of the nodes. - * + *

* This method returns whether the augmentation information in any of the ancestors of this node might have been * affected by changes in this subtree since the last call to augment(). In the usual case, where the augmentation * information depends only on the information in this node and the augmentation information in its immediate @@ -79,7 +85,7 @@ public abstract class RedBlackNode> implements Compara * calling augment() differed from the size field of the left child plus the size field of the right child plus one. * False positives are permitted. The return value is unspecified if we have not called augment() on this node * before. - * + *

* This method may assume that this is not a leaf node. It may not assume that the augmentation information stored * in any of the tree's nodes is correct. However, if the augmentation information stored in all of the node's * descendants is correct, then the augmentation information stored in this node must be correct after calling @@ -94,7 +100,7 @@ public abstract class RedBlackNode> implements Compara * of RedBlackNode. For example, if this stores the size of the subtree rooted at this node, this should throw a * RuntimeException if the size field of this is not equal to the size field of the left child plus the size field * of the right child plus one. Note that we may call this on a leaf node. - * + *

* assertSubtreeIsValid() calls assertNodeIsValid() on each node, or at least starts to do so until it detects a * problem. assertNodeIsValid() should assume the node is in a tree that satisfies all properties common to all * red-black trees, as assertSubtreeIsValid() is responsible for such checks. assertNodeIsValid() should be @@ -107,58 +113,68 @@ public abstract class RedBlackNode> implements Compara } - /** Returns whether this is a leaf node. */ + /** + * Returns whether this is a leaf node. + */ public boolean isLeaf() { return left == null; } - /** Returns the root of the tree that contains this node. */ + /** + * Returns the root of the tree that contains this node. + */ public N root() { @SuppressWarnings("unchecked") - N node = (N)this; + N node = (N) this; while (node.parent != null) { node = node.parent; } return node; } - /** Returns the first node in the subtree rooted at this node, if any. */ + /** + * Returns the first node in the subtree rooted at this node, if any. + */ public N min() { if (isLeaf()) { return null; } @SuppressWarnings("unchecked") - N node = (N)this; + N node = (N) this; while (!node.left.isLeaf()) { node = node.left; } return node; } - /** Returns the last node in the subtree rooted at this node, if any. */ + /** + * Returns the last node in the subtree rooted at this node, if any. + */ public N max() { if (isLeaf()) { return null; } @SuppressWarnings("unchecked") - N node = (N)this; + N node = (N) this; while (!node.right.isLeaf()) { node = node.right; } return node; } - /** Returns the node immediately before this in the tree that contains this node, if any. */ + /** + * Returns the node immediately before this in the tree that contains this node, if any. + */ public N predecessor() { if (!left.isLeaf()) { N node; - for (node = left; !node.right.isLeaf(); node = node.right); + for (node = left; !node.right.isLeaf(); node = node.right) ; return node; } else if (parent == null) { return null; } else { @SuppressWarnings("unchecked") - N node = (N)this; + N node = (N) this; while (node.parent != null && node.parent.left == node) { node = node.parent; } @@ -166,17 +182,19 @@ public abstract class RedBlackNode> implements Compara } } - /** Returns the node immediately after this in the tree that contains this node, if any. */ + /** + * Returns the node immediately after this in the tree that contains this node, if any. + */ public N successor() { if (!right.isLeaf()) { N node; - for (node = right; !node.left.isLeaf(); node = node.left); + for (node = right; !node.left.isLeaf(); node = node.left) ; return node; } else if (parent == null) { return null; } else { @SuppressWarnings("unchecked") - N node = (N)this; + N node = (N) this; while (node.parent != null && node.parent.right == node) { node = node.parent; } @@ -188,6 +206,7 @@ public abstract class RedBlackNode> implements Compara * Performs a left rotation about this node. This method assumes that !isLeaf() && !right.isLeaf(). It calls * augment() on this node and on its resulting parent. However, it does not call augment() on any of the resulting * parent's ancestors, because that is normally the responsibility of the caller. + * * @return The return value from calling augment() on the resulting parent. */ public boolean rotateLeft() { @@ -197,7 +216,7 @@ public abstract class RedBlackNode> implements Compara N newParent = right; right = newParent.left; @SuppressWarnings("unchecked") - N nThis = (N)this; + N nThis = (N) this; if (!right.isLeaf()) { right.parent = nThis; } @@ -219,6 +238,7 @@ public abstract class RedBlackNode> implements Compara * Performs a right rotation about this node. This method assumes that !isLeaf() && !left.isLeaf(). It calls * augment() on this node and on its resulting parent. However, it does not call augment() on any of the resulting * parent's ancestors, because that is normally the responsibility of the caller. + * * @return The return value from calling augment() on the resulting parent. */ public boolean rotateRight() { @@ -228,7 +248,7 @@ public abstract class RedBlackNode> implements Compara N newParent = left; left = newParent.right; @SuppressWarnings("unchecked") - N nThis = (N)this; + N nThis = (N) this; if (!left.isLeaf()) { left.parent = nThis; } @@ -252,6 +272,7 @@ public abstract class RedBlackNode> implements Compara * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs * any rotations by calling rotateLeft() and rotateRight(). This method is more efficient than fixInsertion if * "augment" is false or augment() might return false. + * * @param augment Whether to set the augmentation information for "node" and its ancestors, by calling augment(). */ public void fixInsertionWithoutGettingRoot(boolean augment) { @@ -339,6 +360,7 @@ public abstract class RedBlackNode> implements Compara * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs * any rotations by calling rotateLeft() and rotateRight(). + * * @param augment Whether to set the augmentation information for "node" and its ancestors, by calling augment(). * @return The root of the resulting tree. */ @@ -352,6 +374,7 @@ public abstract class RedBlackNode> implements Compara * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs * any rotations by calling rotateLeft() and rotateRight(). + * * @return The root of the resulting tree. */ public N fixInsertion() { @@ -359,27 +382,29 @@ public abstract class RedBlackNode> implements Compara return root(); } - /** Returns a Comparator that compares instances of N using their natural order, as in N.compareTo. */ + /** + * Returns a Comparator that compares instances of N using their natural order, as in N.compareTo. + */ @SuppressWarnings({"rawtypes", "unchecked"}) private Comparator naturalOrder() { - Comparator comparator = (Comparator)NATURAL_ORDER; - return (Comparator)comparator; + Comparator comparator = (Comparator) NATURAL_ORDER; + return (Comparator) comparator; } /** * Inserts the specified node into the tree rooted at this node. Assumes this is the root. We treat newNode as a * solitary node that does not belong to any tree, and we ignore its initial "parent", "left", "right", and isRed * fields. - * + *

* If it is not efficient or convenient to find the location for a node using a Comparator, then you should manually * add the node to the appropriate location, color it red, and call fixInsertion(). * - * @param newNode The node to insert. + * @param newNode The node to insert. * @param allowDuplicates Whether to insert newNode if there is an equal node in the tree. To check whether we - * inserted newNode, check whether newNode.parent is null and the return value differs from newNode. - * @param comparator A comparator indicating where to put the node. If this is null, we use the nodes' natural - * order, as in N.compareTo. If you are passing null, then you must override the compareTo method, because the - * default implementation requires the nodes to already be in the same tree. + * inserted newNode, check whether newNode.parent is null and the return value differs from newNode. + * @param comparator A comparator indicating where to put the node. If this is null, we use the nodes' natural + * order, as in N.compareTo. If you are passing null, then you must override the compareTo method, because the + * default implementation requires the nodes to already be in the same tree. * @return The root of the resulting tree. */ public N insert(N newNode, boolean allowDuplicates, Comparator comparator) { @@ -387,7 +412,7 @@ public abstract class RedBlackNode> implements Compara throw new IllegalArgumentException("This is not the root of a tree"); } @SuppressWarnings("unchecked") - N nThis = (N)this; + N nThis = (N) this; if (isLeaf()) { newNode.isRed = false; newNode.left = nThis; @@ -436,6 +461,7 @@ public abstract class RedBlackNode> implements Compara /** * Moves this node to its successor's former position in the tree and vice versa, i.e. sets the "left", "right", * "parent", and isRed fields of each. This method assumes that this is not a leaf node. + * * @return The node with which we swapped. */ private N swapWithSuccessor() { @@ -458,7 +484,7 @@ public abstract class RedBlackNode> implements Compara } @SuppressWarnings("unchecked") - N nThis = (N)this; + N nThis = (N) this; isRed = oldReplacementIsRed; left = oldReplacementLeft; right = oldReplacementRight; @@ -575,7 +601,7 @@ public abstract class RedBlackNode> implements Compara * Removes this node from the tree that contains it. The effect of this method on the fields of this node is * unspecified. This method assumes that this is not a leaf node. This method is more efficient than remove() if * augment() might return false. - * + *

* If the node has two children, we begin by moving the node's successor to its former position, by changing the * successor's "left", "right", "parent", and isRed fields. */ @@ -665,7 +691,7 @@ public abstract class RedBlackNode> implements Compara /** * Removes this node from the tree that contains it. The effect of this method on the fields of this node is * unspecified. This method assumes that this is not a leaf node. - * + *

* If the node has two children, we begin by moving the node's successor to its former position, by changing the * successor's "left", "right", "parent", and isRed fields. * @@ -697,13 +723,14 @@ public abstract class RedBlackNode> implements Compara * "iterator", in iteration order. This method is responsible for setting the "left", "right", "parent", and isRed * fields of the nodes, and calling augment() as appropriate. It ignores the initial values of the "left", "right", * "parent", and isRed fields. + * * @param iterator The nodes. - * @param size The number of nodes. - * @param height The "height" of the subtree's root node above the deepest leaf in the tree that contains it. Since - * insertion fixup is slow if there are too many red nodes and deleteion fixup is slow if there are too few red - * nodes, we compromise and have red nodes at every fourth level. We color a node red iff its "height" is equal - * to 1 mod 4. - * @param leaf The leaf node. + * @param size The number of nodes. + * @param height The "height" of the subtree's root node above the deepest leaf in the tree that contains it. Since + * insertion fixup is slow if there are too many red nodes and deleteion fixup is slow if there are too few red + * nodes, we compromise and have red nodes at every fourth level. We color a node red iff its "height" is equal + * to 1 mod 4. + * @param leaf The leaf node. * @return The root of the subtree. */ private static > N createTree( @@ -735,8 +762,9 @@ public abstract class RedBlackNode> implements Compara * method is responsible for setting the "left", "right", "parent", and isRed fields of the nodes (excluding * "leaf"), and calling augment() as appropriate. It ignores the initial values of the "left", "right", "parent", * and isRed fields. + * * @param nodes The nodes. - * @param leaf The leaf node. + * @param leaf The leaf node. * @return The root of the tree. */ public static > N createTree(Collection nodes, N leaf) { @@ -762,7 +790,7 @@ public abstract class RedBlackNode> implements Compara * all of these nodes. This method destroys the trees rooted at "this" and "last". We treat "pivot" as a solitary * node that does not belong to any tree, and we ignore its initial "parent", "left", "right", and isRed fields. * This method assumes that this node and "last" are the roots of their respective trees. - * + *

* This method takes O(log N) time. It is more efficient than inserting "pivot" and then calling concatenate(last). * It is considerably more efficient than inserting "pivot" and all of the nodes in "last". */ @@ -783,7 +811,7 @@ public abstract class RedBlackNode> implements Compara // Compute the black height of the trees int firstBlackHeight = 0; @SuppressWarnings("unchecked") - N first = (N)this; + N first = (N) this; for (N node = first; node != null; node = node.right) { if (!node.isRed) { firstBlackHeight++; @@ -868,7 +896,7 @@ public abstract class RedBlackNode> implements Compara return last; } else if (last.isLeaf()) { @SuppressWarnings("unchecked") - N nThis = (N)this; + N nThis = (N) this; return nThis; } else { N node = last.min(); @@ -884,6 +912,7 @@ public abstract class RedBlackNode> implements Compara * destructive, meaning it does not preserve the original tree. It assumes that this node is the root and is in the * same tree as splitNode. It takes O(log N) time. It is considerably more efficient than removing all of the * nodes at or after splitNode and then creating a new tree from those nodes. + * * @param The node at which to split the tree. * @return An array consisting of the resulting trees. */ @@ -929,7 +958,7 @@ public abstract class RedBlackNode> implements Compara } @SuppressWarnings("unchecked") - N node = (N)this; + N node = (N) this; N first = null; N firstParent = null; N last = null; @@ -1082,7 +1111,7 @@ public abstract class RedBlackNode> implements Compara last.augment(); @SuppressWarnings("unchecked") - N[] result = (N[])Array.newInstance(getClass(), 2); + N[] result = (N[]) Array.newInstance(getClass(), 2); result[0] = first; result[1] = last; return result; @@ -1092,7 +1121,7 @@ public abstract class RedBlackNode> implements Compara * Returns the lowest common ancestor of this node and "other" - the node that is an ancestor of both and is not the * parent of a node that is an ancestor of both. Assumes that this is in the same tree as "other". Assumes that * neither "this" nor "other" is a leaf node. This method may return "this" or "other". - * + *

* Note that while it is possible to compute the lowest common ancestor in O(P) time, where P is the length of the * path from this node to "other", the "lca" method is not guaranteed to take O(P) time. If your application * requires this, then you should write your own lowest common ancestor method. @@ -1114,7 +1143,7 @@ public abstract class RedBlackNode> implements Compara // Go up to nodes of the same depth @SuppressWarnings("unchecked") - N parent = (N)this; + N parent = (N) this; N otherParent = other; if (depth <= otherDepth) { for (int i = otherDepth; i > depth; i--) { @@ -1142,10 +1171,10 @@ public abstract class RedBlackNode> implements Compara * Returns an integer comparing the position of this node in the tree that contains it with that of "other". Returns * a negative number if this is earlier, a positive number if this is later, and 0 if this is at the same position. * Assumes that this is in the same tree as "other". Assumes that neither "this" nor "other" is a leaf node. - * + *

* The base class's implementation takes O(log N) time. If a RedBlackNode subclass stores a value used to order the * nodes, then it could override compareTo to compare the nodes' values, which would take O(1) time. - * + *

* Note that while it is possible to compare the positions of two nodes in O(P) time, where P is the length of the * path from this node to "other", the default implementation of compareTo is not guaranteed to take O(P) time. If * your application requires this, then you should write your own comparison method. @@ -1224,7 +1253,9 @@ public abstract class RedBlackNode> implements Compara } } - /** Throws a RuntimeException if the RedBlackNode fields of this are not correct for a leaf node. */ + /** + * Throws a RuntimeException if the RedBlackNode fields of this are not correct for a leaf node. + */ private void assertIsValidLeaf() { if (left != null || right != null || parent != null || isRed) { throw new RuntimeException("A leaf node's \"left\", \"right\", \"parent\", or isRed field is incorrect"); @@ -1234,14 +1265,15 @@ public abstract class RedBlackNode> implements Compara /** * Throws a RuntimeException if the subtree rooted at this node does not satisfy the red-black properties, excluding * the requirement that the root be black, or it contains a repeated node other than a leaf node. + * * @param blackHeight The required number of black nodes in each path from this to a leaf node, including this and - * the leaf node. - * @param visited The nodes we have reached thus far, other than leaf nodes. This method adds the non-leaf nodes in - * the subtree rooted at this node to "visited". + * the leaf node. + * @param visited The nodes we have reached thus far, other than leaf nodes. This method adds the non-leaf nodes in + * the subtree rooted at this node to "visited". */ private void assertSubtreeIsValidRedBlack(int blackHeight, Set> visited) { @SuppressWarnings("unchecked") - N nThis = (N)this; + N nThis = (N) this; if (left == null || right == null) { assertIsValidLeaf(); if (blackHeight != 1) { @@ -1276,7 +1308,9 @@ public abstract class RedBlackNode> implements Compara } } - /** Calls assertNodeIsValid() on every node in the subtree rooted at this node. */ + /** + * Calls assertNodeIsValid() on every node in the subtree rooted at this node. + */ private void assertNodesAreValid() { assertNodeIsValid(); if (left != null) { @@ -1304,7 +1338,7 @@ public abstract class RedBlackNode> implements Compara Set> nodes = new HashSet>(); int blackHeight = 0; @SuppressWarnings("unchecked") - N node = (N)this; + N node = (N) this; while (node != null) { if (!nodes.add(new Reference(node))) { throw new RuntimeException("The tree contains a repeated non-leaf node"); @@ -1333,14 +1367,15 @@ public abstract class RedBlackNode> implements Compara * Throws a RuntimeException if the nodes in the subtree rooted at this node are not in the specified order or they * do not lie in the specified range. Assumes that the subtree rooted at this node is a valid binary tree, i.e. it * has no repeated nodes other than leaf nodes. + * * @param comparator A comparator indicating how the nodes should be ordered. - * @param start The lower limit for nodes in the subtree, if any. - * @param end The upper limit for nodes in the subtree, if any. + * @param start The lower limit for nodes in the subtree, if any. + * @param end The upper limit for nodes in the subtree, if any. */ private void assertOrderIsValid(Comparator comparator, N start, N end) { if (!isLeaf()) { @SuppressWarnings("unchecked") - N nThis = (N)this; + N nThis = (N) this; if (start != null && comparator.compare(nThis, start) < 0) { throw new RuntimeException("The nodes are not ordered correctly"); } @@ -1359,8 +1394,9 @@ public abstract class RedBlackNode> implements Compara * Assumes that this is a valid binary tree, i.e. there are no repeated nodes other than leaf nodes. This method is * useful for debugging. RedBlackNode subclasses may want to override assertSubtreeIsValid() to call * assertOrderIsValid. + * * @param comparator A comparator indicating how the nodes should be ordered. If this is null, we use the nodes' - * natural order, as in N.compareTo. + * natural order, as in N.compareTo. */ public void assertOrderIsValid(Comparator comparator) { if (comparator == null) { diff --git a/src/main/java/com/github/btrekkie/red_black_node/Reference.java b/src/main/java/com/github/btrekkie/red_black_node/Reference.java index 410b9fa28..6fbd9ddeb 100644 --- a/src/main/java/com/github/btrekkie/red_black_node/Reference.java +++ b/src/main/java/com/github/btrekkie/red_black_node/Reference.java @@ -5,10 +5,13 @@ package com.github.btrekkie.red_black_node; /** * Wraps a value using reference equality. In other words, two references are equal only if their values are the same * object instance, as in ==. + * * @param The type of value. */ class Reference { - /** The value this wraps. */ + /** + * The value this wraps. + */ private final T value; public Reference(T value) { @@ -19,7 +22,7 @@ class Reference { if (!(obj instanceof Reference)) { return false; } - Reference reference = (Reference)obj; + Reference reference = (Reference) obj; return value == reference.value; } diff --git a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderCollection.java b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderCollection.java index 8b5102471..90374ca52 100644 --- a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderCollection.java +++ b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderCollection.java @@ -11,7 +11,9 @@ import java.util.Comparator; /* We implement an ArbitraryOrderCollection using a red-black tree. We order the nodes arbitrarily. */ public class ArbitraryOrderCollection { - /** The Comparator for ordering ArbitraryOrderNodes. */ + /** + * The Comparator for ordering ArbitraryOrderNodes. + */ private static final Comparator NODE_COMPARATOR = new Comparator() { @Override public int compare(ArbitraryOrderNode node1, ArbitraryOrderNode node2) { @@ -19,10 +21,14 @@ public class ArbitraryOrderCollection { } }; - /** The root node of the tree. */ + /** + * The root node of the tree. + */ private ArbitraryOrderNode root = new ArbitraryOrderNode(); - /** Adds and returns a new value for ordering. */ + /** + * Adds and returns a new value for ordering. + */ public ArbitraryOrderValue createValue() { ArbitraryOrderNode node = new ArbitraryOrderNode(); root = root.insert(node, true, NODE_COMPARATOR); diff --git a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderNode.java b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderNode.java index b5d28d9be..8a889bb9a 100644 --- a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderNode.java +++ b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderNode.java @@ -2,7 +2,9 @@ package com.github.btrekkie.arbitrary_order_collection; import com.github.btrekkie.red_black_node.RedBlackNode; -/** A node in an ArbitraryOrderCollection tree. See ArbitraryOrderCollection. */ +/** + * A node in an ArbitraryOrderCollection tree. See ArbitraryOrderCollection. + */ class ArbitraryOrderNode extends RedBlackNode { } diff --git a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderValue.java b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderValue.java index c12b995ad..160c4ee75 100644 --- a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderValue.java +++ b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderValue.java @@ -5,7 +5,9 @@ package com.github.btrekkie.arbitrary_order_collection; * compareTo. */ public class ArbitraryOrderValue implements Comparable { - /** The node that establishes this value's relative position. */ + /** + * The node that establishes this value's relative position. + */ final ArbitraryOrderNode node; ArbitraryOrderValue(ArbitraryOrderNode node) { diff --git a/src/test/java/com/github/btrekkie/arbitrary_order_collection/test/ArbitraryOrderCollectionTest.java b/src/test/java/com/github/btrekkie/arbitrary_order_collection/test/ArbitraryOrderCollectionTest.java index 9d855d17d..ad36a5c62 100644 --- a/src/test/java/com/github/btrekkie/arbitrary_order_collection/test/ArbitraryOrderCollectionTest.java +++ b/src/test/java/com/github/btrekkie/arbitrary_order_collection/test/ArbitraryOrderCollectionTest.java @@ -1,19 +1,20 @@ package com.github.btrekkie.arbitrary_order_collection.test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import com.github.btrekkie.arbitrary_order_collection.ArbitraryOrderCollection; +import com.github.btrekkie.arbitrary_order_collection.ArbitraryOrderValue; +import org.junit.Test; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.junit.Test; - -import com.github.btrekkie.arbitrary_order_collection.ArbitraryOrderCollection; -import com.github.btrekkie.arbitrary_order_collection.ArbitraryOrderValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class ArbitraryOrderCollectionTest { - /** Tests ArbitraryOrderCollection. */ + /** + * Tests ArbitraryOrderCollection. + */ @Test public void test() { ArbitraryOrderCollection collection = new ArbitraryOrderCollection(); diff --git a/src/test/java/com/github/btrekkie/connectivity/test/SumAndMax.java b/src/test/java/com/github/btrekkie/connectivity/test/SumAndMax.java index 393c3599f..1b2a89b76 100644 --- a/src/test/java/com/github/btrekkie/connectivity/test/SumAndMax.java +++ b/src/test/java/com/github/btrekkie/connectivity/test/SumAndMax.java @@ -2,14 +2,18 @@ package com.github.btrekkie.connectivity.test; import com.github.btrekkie.connectivity.Augmentation; -/** Stores two values: a sum and a maximum. Used for testing augmentation in ConnGraph. */ +/** + * Stores two values: a sum and a maximum. Used for testing augmentation in ConnGraph. + */ class SumAndMax { - /** An Augmentation that combines two SumAndMaxes into one. */ + /** + * An Augmentation that combines two SumAndMaxes into one. + */ public static final Augmentation AUGMENTATION = new Augmentation() { @Override public Object combine(Object value1, Object value2) { - SumAndMax sumAndMax1 = (SumAndMax)value1; - SumAndMax sumAndMax2 = (SumAndMax)value2; + SumAndMax sumAndMax1 = (SumAndMax) value1; + SumAndMax sumAndMax2 = (SumAndMax) value2; return new SumAndMax(sumAndMax1.sum + sumAndMax2.sum, Math.max(sumAndMax1.max, sumAndMax2.max)); } }; @@ -28,7 +32,7 @@ class SumAndMax { if (!(obj instanceof SumAndMax)) { return false; } - SumAndMax sumAndMax = (SumAndMax)obj; + SumAndMax sumAndMax = (SumAndMax) obj; return sum == sumAndMax.sum && max == sumAndMax.max; } diff --git a/src/test/java/com/github/btrekkie/interval_tree/IntervalTree.java b/src/test/java/com/github/btrekkie/interval_tree/IntervalTree.java index d5e88624e..aa0204517 100644 --- a/src/test/java/com/github/btrekkie/interval_tree/IntervalTree.java +++ b/src/test/java/com/github/btrekkie/interval_tree/IntervalTree.java @@ -8,16 +8,21 @@ package com.github.btrekkie.interval_tree; * interval. Each node is augmented with the maximum ending value of an interval in the subtree rooted at the node. */ public class IntervalTree { - /** The root node of the tree. */ + /** + * The root node of the tree. + */ private IntervalTreeNode root = IntervalTreeNode.LEAF; - /** Adds the specified interval to this. */ + /** + * Adds the specified interval to this. + */ public void addInterval(IntervalTreeInterval interval) { root = root.insert(new IntervalTreeNode(interval), true, null); } /** * Removes the specified interval from this, if it is present. + * * @param interval The interval. * @return Whether the interval was present. */ diff --git a/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeInterval.java b/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeInterval.java index e9f38b9d9..182eb37c6 100644 --- a/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeInterval.java +++ b/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeInterval.java @@ -4,10 +4,14 @@ package com.github.btrekkie.interval_tree; * An inclusive range of values [start, end]. Two intervals are equal if they have the same starting and ending values. */ public class IntervalTreeInterval { - /** The smallest value in the range. */ + /** + * The smallest value in the range. + */ public final double start; - /** The largest value in the range. */ + /** + * The largest value in the range. + */ public final double end; public IntervalTreeInterval(double start, double end) { @@ -22,7 +26,7 @@ public class IntervalTreeInterval { if (!(obj instanceof IntervalTreeInterval)) { return false; } - IntervalTreeInterval interval = (IntervalTreeInterval)obj; + IntervalTreeInterval interval = (IntervalTreeInterval) obj; return start == interval.start && end == interval.end; } } diff --git a/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeNode.java b/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeNode.java index d75004e77..7b6bffaa7 100644 --- a/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeNode.java +++ b/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeNode.java @@ -7,13 +7,19 @@ import com.github.btrekkie.red_black_node.RedBlackNode; * nodes as suggested in the comments for the implementation of IntervalTree. */ class IntervalTreeNode extends RedBlackNode { - /** The dummy leaf node. */ + /** + * The dummy leaf node. + */ public static final IntervalTreeNode LEAF = new IntervalTreeNode(); - /** The interval stored in this node. */ + /** + * The interval stored in this node. + */ public IntervalTreeInterval interval; - /** The maximum ending value of an interval in the subtree rooted at this node. */ + /** + * The maximum ending value of an interval in the subtree rooted at this node. + */ public double maxEnd; public IntervalTreeNode(IntervalTreeInterval interval) { @@ -21,7 +27,9 @@ class IntervalTreeNode extends RedBlackNode { maxEnd = interval.end; } - /** Constructs a new dummy leaf node. */ + /** + * Constructs a new dummy leaf node. + */ private IntervalTreeNode() { interval = null; maxEnd = Double.NEGATIVE_INFINITY; diff --git a/src/test/java/com/github/btrekkie/interval_tree/test/IntervalTreeTest.java b/src/test/java/com/github/btrekkie/interval_tree/test/IntervalTreeTest.java index cf0dbdfa6..5af2bd6d2 100644 --- a/src/test/java/com/github/btrekkie/interval_tree/test/IntervalTreeTest.java +++ b/src/test/java/com/github/btrekkie/interval_tree/test/IntervalTreeTest.java @@ -1,17 +1,15 @@ package com.github.btrekkie.interval_tree.test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - import com.github.btrekkie.interval_tree.IntervalTree; import com.github.btrekkie.interval_tree.IntervalTreeInterval; +import org.junit.Test; + +import static org.junit.Assert.*; public class IntervalTreeTest { - /** Tests IntervalTree. */ + /** + * Tests IntervalTree. + */ @Test public void test() { IntervalTree tree = new IntervalTree(); diff --git a/src/test/java/com/github/btrekkie/red_black_node/test/RedBlackNodeTest.java b/src/test/java/com/github/btrekkie/red_black_node/test/RedBlackNodeTest.java index 4d571aeb1..b487e54fe 100644 --- a/src/test/java/com/github/btrekkie/red_black_node/test/RedBlackNodeTest.java +++ b/src/test/java/com/github/btrekkie/red_black_node/test/RedBlackNodeTest.java @@ -1,11 +1,11 @@ package com.github.btrekkie.red_black_node.test; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import org.junit.Test; import java.util.Comparator; -import org.junit.Test; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * Tests RedBlackNode. Most of the testing for RedBlackNode takes place in TreeListTest, IntervalTreeTest, @@ -30,8 +30,9 @@ public class RedBlackNodeTest { /** * Returns whether the nodes in the subtree rooted at the specified node are ordered correctly, as in * TestRedBlackNode.assertOrderIsValid. + * * @param comparator A comparator indicating how the nodes should be ordered. If this is null, we use the nodes' - * natural ordering, as in TestRedBlackNode.compare. + * natural ordering, as in TestRedBlackNode.compare. */ private boolean isOrderValid(TestRedBlackNode node, Comparator comparator) { try { @@ -42,7 +43,9 @@ public class RedBlackNodeTest { } } - /** Tests RedBlackNode.assertSubtreeIsValid() and RedBlackNode.assertOrderIsValid. */ + /** + * Tests RedBlackNode.assertSubtreeIsValid() and RedBlackNode.assertOrderIsValid. + */ @Test public void testAssertIsValid() { // Create a perfectly balanced tree of height 3 @@ -129,12 +132,12 @@ public class RedBlackNodeTest { node2.value = 3; assertFalse(isOrderValid(node3, null)); assertFalse( - isOrderValid(node3, new Comparator() { - @Override - public int compare(TestRedBlackNode node1, TestRedBlackNode node2) { - return node1.value - node2.value; - } - })); + isOrderValid(node3, new Comparator() { + @Override + public int compare(TestRedBlackNode node1, TestRedBlackNode node2) { + return node1.value - node2.value; + } + })); node3.value = 3; node2.value = 2; @@ -161,11 +164,11 @@ public class RedBlackNodeTest { assertTrue(isOrderValid(node0, null)); assertTrue(isOrderValid(TestRedBlackNode.LEAF, null)); assertTrue( - isOrderValid(node3, new Comparator() { - @Override - public int compare(TestRedBlackNode node1, TestRedBlackNode node2) { - return node1.value - node2.value; - } - })); + isOrderValid(node3, new Comparator() { + @Override + public int compare(TestRedBlackNode node1, TestRedBlackNode node2) { + return node1.value - node2.value; + } + })); } } diff --git a/src/test/java/com/github/btrekkie/red_black_node/test/TestRedBlackNode.java b/src/test/java/com/github/btrekkie/red_black_node/test/TestRedBlackNode.java index 8e3b78cd8..86ab1cb3a 100644 --- a/src/test/java/com/github/btrekkie/red_black_node/test/TestRedBlackNode.java +++ b/src/test/java/com/github/btrekkie/red_black_node/test/TestRedBlackNode.java @@ -2,22 +2,32 @@ package com.github.btrekkie.red_black_node.test; import com.github.btrekkie.red_black_node.RedBlackNode; -/** A RedBlackNode for RedBlackNodeTest. */ +/** + * A RedBlackNode for RedBlackNodeTest. + */ class TestRedBlackNode extends RedBlackNode { - /** The dummy leaf node. */ + /** + * The dummy leaf node. + */ public static final TestRedBlackNode LEAF = new TestRedBlackNode(); - /** The value stored in this node. "value" is unspecified if this is a leaf node. */ + /** + * The value stored in this node. "value" is unspecified if this is a leaf node. + */ public int value; - /** Whether this node is considered valid, as in assertNodeIsValid(). */ + /** + * Whether this node is considered valid, as in assertNodeIsValid(). + */ public boolean isValid = true; public TestRedBlackNode(int value) { this.value = value; } - /** Constructs a new dummy leaf node. */ + /** + * Constructs a new dummy leaf node. + */ private TestRedBlackNode() { } diff --git a/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMin.java b/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMin.java index 63634c9f8..7c8e1c4ba 100644 --- a/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMin.java +++ b/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMin.java @@ -1,14 +1,20 @@ package com.github.btrekkie.sub_array_min; -/** A list of integers. SubArrayMin provides the ability to quickly determine the minimum value in a given sublist. */ +/** + * A list of integers. SubArrayMin provides the ability to quickly determine the minimum value in a given sublist. + */ /* We implement SubArrayMin using a red-black tree augmented by subtree size and minimum value. Using the subtree size * augmentation, we can find the node at a given index. */ public class SubArrayMin { - /** The root node. */ + /** + * The root node. + */ private SubArrayMinNode root = SubArrayMinNode.LEAF; - /** Appends the specified value to the end of the list. */ + /** + * Appends the specified value to the end of the list. + */ public void add(int value) { SubArrayMinNode newNode = new SubArrayMinNode(value); newNode.left = SubArrayMinNode.LEAF; @@ -25,7 +31,9 @@ public class SubArrayMin { } } - /** Returns the node for the element with the specified index. Assumes "index" is in the range [0, root.size). */ + /** + * Returns the node for the element with the specified index. Assumes "index" is in the range [0, root.size). + */ private SubArrayMinNode getNode(int index) { if (index < 0 || index >= root.size) { throw new IndexOutOfBoundsException("Index " + index + " is not in the range [0, " + root.size + ")"); diff --git a/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMinNode.java b/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMinNode.java index 1839b7220..e76860f09 100644 --- a/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMinNode.java +++ b/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMinNode.java @@ -2,18 +2,28 @@ package com.github.btrekkie.sub_array_min; import com.github.btrekkie.red_black_node.RedBlackNode; -/** A node in a SubArrayMin object. See the comments for the implementation of that class. */ +/** + * A node in a SubArrayMin object. See the comments for the implementation of that class. + */ class SubArrayMinNode extends RedBlackNode { - /** The dummy leaf node. */ + /** + * The dummy leaf node. + */ public static final SubArrayMinNode LEAF = new SubArrayMinNode(); - /** The element stored in the node. The value is unspecified if this is a leaf node. */ + /** + * The element stored in the node. The value is unspecified if this is a leaf node. + */ public final int value; - /** The number of elements in the subtree rooted at this node. */ + /** + * The number of elements in the subtree rooted at this node. + */ public int size; - /** The minimum element in the subtree rooted at this node. This is Integer.MAX_VALUE if this is a leaf node. */ + /** + * The minimum element in the subtree rooted at this node. This is Integer.MAX_VALUE if this is a leaf node. + */ public int min; public SubArrayMinNode(int value) { diff --git a/src/test/java/com/github/btrekkie/sub_array_min/test/SubArrayMinTest.java b/src/test/java/com/github/btrekkie/sub_array_min/test/SubArrayMinTest.java index 5daa7e053..95266b387 100644 --- a/src/test/java/com/github/btrekkie/sub_array_min/test/SubArrayMinTest.java +++ b/src/test/java/com/github/btrekkie/sub_array_min/test/SubArrayMinTest.java @@ -1,13 +1,14 @@ package com.github.btrekkie.sub_array_min.test; +import com.github.btrekkie.sub_array_min.SubArrayMin; +import org.junit.Test; + import static org.junit.Assert.assertEquals; -import org.junit.Test; - -import com.github.btrekkie.sub_array_min.SubArrayMin; - public class SubArrayMinTest { - /** Tests SubArrayMin. */ + /** + * Tests SubArrayMin. + */ @Test public void test() { SubArrayMin sam = new SubArrayMin();