是否有人知道Java的通用树(节点可能有多个子节点)实现?它应来自一个值得信赖的来源,必须经过全面测试。
我自己实施它似乎并不合适。几乎让我想起大学时代,我们应该自己写完所有的藏品。
编辑:在java.net上找到this project,可能值得研究。答案 0 :(得分:23)
来了:
abstract class TreeNode implements Iterable<TreeNode> {
private Set<TreeNode> children;
public TreeNode() {
children = new HashSet<TreeNode>();
}
public boolean addChild(TreeNode n) {
return children.add(n);
}
public boolean removeChild(TreeNode n) {
return children.remove(n);
}
public Iterator<TreeNode> iterator() {
return children.iterator();
}
}
我很信任,但尚未测试实施。
答案 1 :(得分:10)
Guava 15.0为树遍历引入了一个很好的API,因此您无需在代码库中的数十亿次重新实现它。
即TreeTraverser
和一些专门的实施,例如BinaryTreeTraverser
。
非常欢迎addition以避免重新实施如此简单且带来额外奖励的事情:
请注意,Guava现在还为其Files
实用程序类提供了使用TreeTraverser
的新方法,例如Files.fileTreeTraverser()
为您的文件系统遍历需求提供了TreeTraverser<File>
。
答案 2 :(得分:9)
Collections库中没有Tree类。但是,Swing框架中的是一个。 DefaultTreeModel
我过去曾经使用过它并且运行良好。它会在您的应用程序中引入其他类,尽管这可能是也可能不是。
您还可以使用其他集合模拟树并在其中存储集合。例如。列表清单。
答案 3 :(得分:8)
在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;
}
}
答案 4 :(得分:6)
啊,我打算在我的解决方案中发布一个无耻的插件,看到有人已经发布了一个链接。是的,我有同样的问题,我基本上最终编写了自己的通用树。我已经测试了树节点和树本身。
我将节点实现为具有数据字段和节点列表(该节点的子节点)的对象。
答案 5 :(得分:5)
答案 6 :(得分:2)
我发现了一个绝对出色的库http://jung.sourceforge.net,请参阅javadoc http://jung.sourceforge.net/doc/api/index.html。它不仅仅是图形实现。有了它,您可以可视化和布局图形;此外,它还有一堆标准图形算法,您可以直接使用它们。 去,检查出来!虽然我最终实现了自己的基本图形(之前我不知道JUNG),但我使用这个库进行可视化。它看起来很整洁!
答案 7 :(得分:0)
我使用XML DOM(XML描述树结构),特别是开源XOM(http://www.xom.nu)。这是轻量级的,如果需要,节点可以是子类,并且使用和测试非常高。它可能比您需要的大,但它的优点是任何树导航方法(祖先,兄弟姐妹等)都可以通过XPath完全管理。您还可以序列化树并通过测试的XML方法对其进行转换。还有一个强大的用户社区
答案 8 :(得分:0)
当需要树时,我通常使用以下接口,并相应地实现它。
/**
* Generic node interface
*
* @param <T> type of contained data
* @param <N> self-referential type boundary that captures the implementing type
*/
interface Node<T, N extends Node<T, N>>
{
public T getObject();
public boolean addChild(N node);
public List<N> getChildren();
}
实现可能是
class StringNode implements Node<String, StringNode>
{
private final String value;
public StringNode(String value)
{
this.value = value;
}
@Override
public String getObject()
{
return value;
}
@Override
public boolean addChild(StringNode node)
{
// add child
return false;
}
@Override
public List<StringNode> getChildren()
{
// return children
return Collections.emptyList();
}
}
这里的优势是针对接口实现算法所获得的灵活性。一个相当简单的例子可能是
public <T, N extends Node<T, ? extends N>> N performAlgorithm(N node)
{
if (!node.getChildren().isEmpty())
return node.getChildren().get(0);
return node;
}
该方法可以与接口类型或具体实现一起使用
StringNode sn = new StringNode("0");
Node<String, StringNode> node = sn;
// perform computations on the interface type
Node<String, StringNode> result = performAlgorithm(node);
// or use a concrete implementation
StringNode result2 = performAlgorithm(sn);
答案 9 :(得分:0)
如果需要企业级节点树,则可以查看Java Content Repository(JCR)。但是,它与这里建议的简单的内存中节点树解决方案以及带有SQL和XPath的多用户XML数据库相比,远非如此。