Es bastante difícil hacer una verdadera implementación de árbol genérico en Java que realmente separó las operaciones y propiedades de árbol de las implementaciones subyacentes, es decir, intercambiar un RedBlackTreeNode y anular un par de métodos para obtener una implementación RedBlackTree conservando todo el genérico operaciones que contiene una interfaz BinaryTree.
Además, una abstracción ideal podría intercambiar la representación de árbol de bajo nivel, p. una estructura de árbol binario implícita almacenada en una matriz para una interfaz Heap o una base de nodo con punteros secundarios izquierdo y derecho, o múltiples punteros secundarios, o aumentar cualquiera de los anteriores con punteros padres, o enhebrar los nodos hoja, etc., etc. etc.
Intenté y resolví esto por mí mismo, pero terminé con una interfaz bastante complicada que aún aplica seguridad de tipo. Aquí está el esqueleto de la idea que establece una clase BinaryTree abstracta con una operación no trivial (Euler Tour) que funcionará incluso si se cambia la clase de nodo o la clase de árbol subyacente. Podría probable mejorarse introduciendo la idea de cursores para la navegación y posiciones dentro de la estructura de árbol:
public interface Tree<E, P extends Tree.Entry<E, P>> extends Collection<E>
{
public P getRoot();
public Collection<P> children(P v);
public E getValue(P v);
public static interface Entry<T, Q extends Entry<T, Q>> { }
}
public interface BinaryTree<E, P extends BinaryTree.Entry<E, P>> extends Tree<E, P>
{
public P leftChild(P v);
public P rightChild(P v);
public static interface Entry<T, Q extends Entry<T, Q>> extends Tree.Entry<T, Q>
{
public Q getLeft();
public Q getRight();
}
}
public interface TreeTraversalVisitor<E, P extends BinaryTree.Entry<E, P>, R>
{
public R visitLeft(BinaryTree<E, P> tree, P v, R result);
public R visitCenter(BinaryTree<E, P> tree, P v, R result);
public R visitRight(BinaryTree<E, P> tree, P v, R result);
}
public abstract class AbstractBinaryTree<E, P extends BinaryTree.Entry<E, P>> extends AbstractCollection<E> implements BinaryTree<E, P>
{
public Collection<P> children(P v)
{
Collection<P> c = new ArrayList<P>(2);
if (hasLeft(v))
c.add(v.getLeft());
if (hasRight(v))
c.add(v.getRight());
return c;
}
/**
* Performs an Euler Tour of the binary tree
*/
public static <R, E, P extends BinaryTree.Entry<E, P>>
R eulerTour(BinaryTree<E, P> tree, P v, TreeTraversalVisitor<E, P, R> visitor, R result)
{
if (v == null)
return result;
result = visitor.visitLeft(tree, v, result);
if (tree.hasLeft(v))
result = eulerTour(tree, tree.leftChild(v), visitor, result);
result = visitor.visitCenter(tree, v, result);
if (tree.hasRight(v))
result = eulerTour(tree, tree.rightChild(v), visitor, result);
result = visitor.visitRight(tree, v, result);
return result;
}
}
¿Cómo desea utilizar este árbol? – pjp
es decir, ¿usted mismo está definiendo la estructura (como un árbol genealógico) o son los elementos comparables y desea insertarlos de manera eficiente en el árbol? – pjp
Cada nodo debe ser capaz de mantener una lista de hijos por orden de inserción. Necesito hacer algo como * postorder * transversal (http://en.wikipedia.org/wiki/Tree_traversal), atravesando hijos de un nodo en dirección inversa. –