Довольно сложно сделать настоящую реализацию универсального дерева в Java, которая действительно отделяла бы операции и свойства дерева от базовых реализаций, то есть поменять местами RedBlackTreeNode и переопределить пару методов, чтобы получить реализацию RedBlackTree, сохранив при этом все универсальные операции. что содержит интерфейс BinaryTree.
Кроме того, идеальная абстракция была бы в состоянии поменять низкоуровневое представление дерева, например, неявная двоичная древовидная структура, хранящаяся в массиве для интерфейса Heap или Node-base с левым и правым дочерними указателями, или несколькими дочерними указателями, или добавление любого из вышеперечисленных с помощью родительских указателей, или многопоточность листовых узлов и т. д., и т. д., и т.д.
Я попытался решить это сам, но в итоге получил довольно сложный интерфейс, который все еще обеспечивает безопасность типов. Вот скелет идеи, которая устанавливает абстрактный класс BinaryTree с нетривиальной операцией (Euler Tour), которая будет работать, даже если базовый класс узла или класс дерева изменен. Вероятно, это можно улучшить, введя идею курсоров для навигации и позиций в древовидной структуре:
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;
}
}