/** * Returns the nearest common ancestor to this node and <code>aNode</code>. Returns null, if no * such ancestor exists -- if this node and <code>aNode</code> are in different trees or if <code> * aNode</code> is null. A node is considered an ancestor of itself. * * @see #isNodeAncestor * @see #isNodeDescendant * @param aNode node to find common ancestor with * @return nearest ancestor common to this node and <code>aNode</code>, or null if none */ public TreeNode getSharedAncestor(DefaultMutableTreeNode aNode) { if (aNode == this) { return this; } else if (aNode == null) { return null; } int level1, level2, diff; TreeNode node1, node2; level1 = getLevel(); level2 = aNode.getLevel(); if (level2 > level1) { diff = level2 - level1; node1 = aNode; node2 = this; } else { diff = level1 - level2; node1 = this; node2 = aNode; } // Go up the tree until the nodes are at the same level while (diff > 0) { node1 = node1.getParent(); diff--; } // Move up the tree until we find a common ancestor. Since we know // that both nodes are at the same level, we won't cross paths // unknowingly (if there is a common ancestor, both nodes hit it in // the same iteration). do { if (node1 == node2) { return node1; } node1 = node1.getParent(); node2 = node2.getParent(); } while (node1 != null); // only need to check one -- they're at the // same level so if one is null, the other is if (node1 != null || node2 != null) { throw new Error("nodes should be null"); } return null; }
/** * Returns the root of the tree that contains this node. The root is the ancestor with a null * parent. * * @see #isNodeAncestor * @return the root of the tree that contains this node */ public TreeNode getRoot() { TreeNode ancestor = this; TreeNode previous; do { previous = ancestor; ancestor = ancestor.getParent(); } while (ancestor != null); return previous; }
/** * Returns the number of levels above this node -- the distance from the root to this node. If * this node is the root, returns 0. * * @see #getDepth * @return the number of levels above this node */ public int getLevel() { TreeNode ancestor; int levels = 0; ancestor = this; while ((ancestor = ancestor.getParent()) != null) { levels++; } return levels; }
/** * Returns true if <code>aNode</code> is a child of this node. If <code>aNode</code> is null, this * method returns false. * * @return true if <code>aNode</code> is a child of this node; false if <code>aNode</code> is null */ public boolean isNodeChild(TreeNode aNode) { boolean retval; if (aNode == null) { retval = false; } else { if (getChildCount() == 0) { retval = false; } else { retval = (aNode.getParent() == this); } } return retval; }
/** * Builds the parents of node up to and including the root node, where the original node is the * last element in the returned array. The length of the returned array gives the node's depth in * the tree. * * @param aNode the TreeNode to get the path for * @param depth an int giving the number of steps already taken towards the root (on recursive * calls), used to size the returned array * @return an array of TreeNodes giving the path from the root to the specified node */ protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) { TreeNode[] retNodes; /* Check for null, in case someone passed in a null node, or they passed in an element that isn't rooted at root. */ if (aNode == null) { if (depth == 0) return null; else retNodes = new TreeNode[depth]; } else { depth++; retNodes = getPathToRoot(aNode.getParent(), depth); retNodes[retNodes.length - depth] = aNode; } return retNodes; }
/** * Returns true if <code>anotherNode</code> is an ancestor of this node -- if it is this node, * this node's parent, or an ancestor of this node's parent. (Note that a node is considered an * ancestor of itself.) If <code>anotherNode</code> is null, this method returns false. This * operation is at worst O(h) where h is the distance from the root to this node. * * @see #isNodeDescendant * @see #getSharedAncestor * @param anotherNode node to test as an ancestor of this node * @return true if this node is a descendant of <code>anotherNode</code> */ public boolean isNodeAncestor(TreeNode anotherNode) { if (anotherNode == null) { return false; } TreeNode ancestor = this; do { if (ancestor == anotherNode) { return true; } } while ((ancestor = ancestor.getParent()) != null); return false; }
/** * Returns true if <code>anotherNode</code> is a sibling of (has the same parent as) this node. A * node is its own sibling. If <code>anotherNode</code> is null, returns false. * * @param anotherNode node to test as sibling of this node * @return true if <code>anotherNode</code> is a sibling of this node */ public boolean isNodeSibling(TreeNode anotherNode) { boolean retval; if (anotherNode == null) { retval = false; } else if (anotherNode == this) { retval = true; } else { TreeNode myParent = getParent(); retval = (myParent != null && myParent == anotherNode.getParent()); if (retval && !((DefaultMutableTreeNode) getParent()).isNodeChild(anotherNode)) { throw new Error("sibling has different parent"); } } return retval; }
public PathBetweenNodesEnumeration(TreeNode ancestor, TreeNode descendant) { super(); if (ancestor == null || descendant == null) { throw new IllegalArgumentException("argument is null"); } TreeNode current; stack = new Stack<TreeNode>(); stack.push(descendant); current = descendant; while (current != ancestor) { current = current.getParent(); if (current == null && descendant != ancestor) { throw new IllegalArgumentException( "node " + ancestor + " is not an ancestor of " + descendant); } stack.push(current); } }