/** Returns whether v is an internal node. */
  public boolean isInternal(Position v) throws InvalidPositionException {
    return hasLeft(v);  // if v has a right child it will have a left child
  }
  /** Returns whether v is an external node. */
  public boolean isExternal(Position v) throws InvalidPositionException {
    return !isInternal(v);
  }
  /** Returns whether v is the root node. */
  public boolean isRoot(Position v) throws InvalidPositionException { 
    VectorNode vv = checkPosition(v);
    return vv.index() == 1;
  }
  /** Returns whether v has a left child. */
  public boolean hasLeft(Position v) throws InvalidPositionException { 
    VectorNode vv = checkPosition(v);
    return 2*vv.index() <= size();
  }
  /** Returns whether v has a right child. */
  public boolean hasRight(Position v) throws InvalidPositionException { 
    VectorNode vv = checkPosition(v);
    return 2*vv.index() + 1 <= size();
  }
  /** Returns the root of the tree. */
  public Position root() throws EmptyTreeException {
    if (isEmpty()) throw new EmptyTreeException("Tree is empty");
    return (Position)T.elemAtRank(1);
  } 
  /** Returns the left child of v. */
  public Position left(Position v) 
    throws InvalidPositionException, BoundaryViolationException { 
    if (!hasLeft(v)) throw new BoundaryViolationException("No left child");
    return (Position)T.elemAtRank(2*((VectorNode) v).index());
  }
  /** Returns the right child of v. */ 
  public Position right(Position v) 
    throws InvalidPositionException { 
    if (!hasRight(v)) throw new BoundaryViolationException("No right child");
    return (Position)T.elemAtRank(2*((VectorNode) v).index() + 1);
  }