[英]Generic Binary Search Tree Implementation in Java - calling generic methods, and cast exceptions
[英]Generic tree implementation in Java
有沒有人知道 Java 的通用樹(節點可能有多個子節點)實現? 它應該來自一個值得信賴的來源,並且必須經過全面測試。
自己實施它似乎並不正確。 幾乎讓我想起了我的大學時代,當時我們應該自己寫所有的收藏。
編輯:在 java.net 上找到這個項目,可能值得研究。
它來了:
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();
}
}
我很受信任,但尚未測試實施。
Collections 庫中沒有 Tree 類。 然而,有一個在Swing框架。 默認樹模型
我過去使用過這個,效果很好。 它確實將額外的類引入到您的應用程序中,盡管這可能是可取的,也可能是不可取的。
您還可以使用另一個集合模擬樹並將集合存儲在其中。 例如。 列表列表。
Guava 15.0為樹遍歷引入了一個很好的 API,因此您無需在代碼庫中無數次重新實現它。
即, TreeTraverser
和一些專門的實現,如BinaryTreeTraverser
。
一個非常受歡迎的補充,以避免重新實現如此簡單的東西,並有額外的好處:
請注意,Guava 現在還為其Files
實用程序類提供了使用TreeTraverser
新方法,例如Files.fileTreeTraverser()
,它為您的文件系統遍歷需要提供TreeTraverser<File>
。
在 Java 中做一個真正的通用樹實現是相當困難的,它真正將樹操作和屬性與底層實現分開,即交換一個 RedBlackTreeNode 並覆蓋幾個方法來獲得 RedBlackTree 實現,同時保留 BinaryTree 的所有通用操作界面包含。
此外,理想的抽象將能夠換出低級樹表示,例如存儲在數組中的隱式二叉樹結構,用於堆或具有左右子指針或多個子指針的節點基接口,或用父指針增加上述任何一個,或線程化葉節點等,等等。
我確實嘗試過自己解決這個問題,但最終得到了一個相當復雜的接口,它仍然強制執行類型安全。 這是使用非平凡操作 (Euler Tour) 設置抽象 BinaryTree 類的想法的框架,即使底層節點類或樹類發生更改,該類也能工作。 可以通過在樹結構中引入用於導航和位置的光標的想法來改進它:
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;
}
}
啊,我打算在我的解決方案中發布一個無恥的插件,但看到有人已經發布了一個鏈接。 是的,我遇到了同樣的問題,我基本上最終編寫了自己的通用樹。 我對樹節點和樹本身進行了測試。
我將該節點實現為一個對象,該對象具有一個數據字段和一個節點列表(它們是該節點的子節點)。
我發現了一個非常棒的庫http://jung.sourceforge.net ,請參閱 javadoc http://jung.sourceforge.net/doc/api/index.html 。 它不僅僅是一個圖形實現。 有了它,您可以可視化和布局圖形; 另外,它有一堆標准的圖形算法,你可以開箱即用。 去看看吧! 雖然我最終實現了自己的基本圖(我之前不知道 JUNG),但我使用這個庫進行可視化。 它看起來非常整潔!
我使用 XML DOM(XML 描述樹結構),特別是開源 XOM( http://www.xom.nu )。 這是輕量級的,如果需要,可以對節點進行子類化,並且高度使用和測試。 它可能比您需要的大,但它的優點是任何樹導航方法(祖先、兄弟等)都可以通過 XPath 完全管理。 您還可以序列化樹並通過經過測試的 XML 方法對其進行轉換。 還有一個強大的用戶社區
當需要一棵樹時,我通常使用以下接口,並相應地實現它。
/**
* 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);
如果您需要企業級節點樹,您可以查看 Java Content Repository ( JCR )。 但它遠不是這里建議的簡單的內存節點樹解決方案,而是一個帶有 SQL 和 XPath 的多用戶 XML 數據庫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.