package graph; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; public class Node { final private int value; /* * linked list as opposed to an array list because we treat it as * a queue more than an array. */ final private List children = new LinkedList(); public Node(int value) { this.value = value; } /** * Adds a link to the graph by exploring the children of * each possible new child. This is done with simple * implementation of Djikstra's algorithm, focusing on * finding each edge of the possible new child's children. * * It was conscious choice not to throw an exception when the link * would make the graph cyclical. Exceptions in java can be expensive, * due to the nature of building the stack trace, and cyclical link * does not seem to be an exceptional case. * * @param newChild * @returns boolean true is the link is successful, false if it is not. */ public boolean link(Node newChild) { /* * Again, a linked list because we are treating it as a queue. * No seeking is necessary here. */ List next = new LinkedList(newChild.children); /*this will cut down on the coefficient runtime *by ensuring we do not process the same subtree twice. *the graph rules do allow for a Node to link to both a child and a descendant of *that child. */ Set previous = new HashSet(); while(!next.isEmpty()) { Node current = next.remove(0); if (!previous.contains(current)) { if (this.equals(current)) return false; for (Node child : current.children) next.add(child); } } this.children.add(newChild); return true; } /* * Both the hash and the equals presume * that there will not be duplicate values * added to the graph, thus they only * consider the value during comparison and hashing. */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + value; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof Node)) return false; final Node other = (Node) obj; if (value != other.value) return false; return true; } }