diff --git a/src/mhtree/InternalNode.java b/src/mhtree/InternalNode.java index 060a681f580aa0ff853d403f160ddb083e03bbfe..e409850ec626ba07ebc1fb25f145540ac896fe49 100644 --- a/src/mhtree/InternalNode.java +++ b/src/mhtree/InternalNode.java @@ -4,10 +4,13 @@ import cz.muni.fi.disa.similarityoperators.cover.AbstractRepresentation.Precompu import messif.objects.LocalAbstractObject; import java.io.Serializable; -import java.util.*; -import java.util.function.Function; +import java.util.Collection; +import java.util.List; import java.util.stream.Collectors; +/** + * Represents internal node of MH-Tree, i.e. a non-leaf node. + */ public class InternalNode extends Node implements Serializable { /** @@ -15,52 +18,116 @@ public class InternalNode extends Node implements Serializable { */ private static final long serialVersionUID = 2L; - private final Set<Node> children; + /** + * List of children. + */ + private final List<Node> children; - InternalNode(PrecomputedDistances distances, InsertType insertType, ObjectToNodeDistance objectToNodeDistance) { + InternalNode(PrecomputedDistances distances, InsertType insertType, ObjectToNodeDistance objectToNodeDistance, List<Node> children) { super(distances, insertType, objectToNodeDistance); - children = new HashSet<>(); - } - public void addChildren(List<Node> children) { - this.children.addAll(children); + this.children = children; } - public Set<Node> getChildren() { + /** + * Returns the list of child nodes. + * + * @return the list of child nodes + */ + List<Node> getChildren() { return children; } - public Node getNearestChild(LocalAbstractObject object) { - Map<Node, Double> nodeToObjectDistance = children.stream() - .collect(Collectors.toMap(Function.identity(), node -> node.getDistance(object))); + /** + * Returns the nearest child to the {@code object}. + * + * @param object object to which the distance is measured + * @return the nearest child to the {@code object} + */ + Node getNearestChild(LocalAbstractObject object) { + Node nearestChild = children.get(0); + double minDistance = nearestChild.getDistance(object); - return Collections.min(nodeToObjectDistance.entrySet(), Map.Entry.comparingByValue()).getKey(); + for (Node child : children) { + double distance = child.getDistance(object); + + if (distance < minDistance) { + minDistance = distance; + nearestChild = child; + } + } + + return nearestChild; } - public void addObject(LocalAbstractObject object) { - addNewObject(object); + /** + * Adds {@code object} into this node. + * + * @param object object to be added + */ + void addObject(LocalAbstractObject object) { + addObjectIntoHull(object); } - public Set<LocalAbstractObject> getObjects() { - return children.stream() + /** + * Returns the list of objects stored in node's descendants. + * + * @return the list of objects stored in node's descendants + */ + List<LocalAbstractObject> getObjects() { + return children + .stream() .map(Node::getObjects) .flatMap(Collection::stream) - .collect(Collectors.toSet()); + .collect(Collectors.toList()); } - public int getHeight() { - return children.stream() + /** + * Returns the height of this node. + * + * @return the height of this node + */ + int getHeight() { + return children + .stream() .mapToInt(Node::getHeight) .summaryStatistics() .getMax() + 1; } - public List<Node> getNodesOnLevel(int level) { - if (getLevel() == level) return Collections.singletonList(this); + /** + * Adds this node and this node's descendants into {@code nodes}. + * + * @param nodes list of nodes, where gathered nodes are added + */ + void gatherNodes(List<Node> nodes) { + nodes.add(this); + nodes.addAll(children); + } - return children.stream() - .map(child -> child.getNodesOnLevel(level)) + /** + * Returns a list of leaf nodes under this node. + * + * @return a list of leaf node under this node + */ + List<LeafNode> getLeafNodes() { + return children + .stream() + .map(Node::getLeafNodes) .flatMap(Collection::stream) .collect(Collectors.toList()); } + + /** + * Returns the number of internal nodes in this subtree. + * + * @return the number of internal nodes in this subtree + */ + int getInternalNodesCount() { + return children + .stream() + .filter(Node::isInternal) + .mapToInt(x -> ((InternalNode) x).getInternalNodesCount()) + .sum() + 1; + } }