2011-08-03 3 views
1

単一ルートツリー内の任意のノードから特殊条件を満たす前/次の葉ノードを見つける関数を書く必要があります。java alogrithm:ツリー内の任意のノードから特殊条件を満たす前/次の葉ノードを見つける

interface Node{ 
    /** @return the Node's parent or null if Node is root */ 
    Node getParent(); 

    /** @return true if node is root */ 
    boolean isRoot(); 

    /** @return non-null array of child nodes (zero length for leaf nodes) */ 
    Node[] getChildren(); 

    /** @return the number of child nodes. If node is leaf, value is 0 */ 
    int getChildCount(); 
} 

そして:currentNodeは、ツリー内の任意のノードであり、Nodeは以下のように定義される

Node findNextLeafNode(Node currentNode, Condition condition); 
Node findPretLeafNode(Node currentNode, Condition condition); 

(親最初の順序で)APIは、このようなものになるだろう Conditionインターフェイスは、指定された Nodeに対して制約をチェックするセマンティクスを定義します。

interface Condition{ 
    /** @return true if provided node meets the condition */ 
    boolean check(Node node); 
} 

私の質問:

は、このような一般的なシナリオのための既存のライブラリやアルゴリズムがありますか?私は、スタックベースまたは再帰的アルゴリズムのいずれかにオープンしています。擬似コード、オープンソースライブラリへのリンク、またはあなた自身のコードを共有したいと思った場合は、感謝します。

(ない場合は、私は再び同じホイールを発明し、共有のために、後でそれをここに貼り付けるために時間を費やす必要があります。)

感謝。

----------------------------- getNext().........メソッドを書く

// currentNode must be descendant of root 
public static Node getNextNode(Node currentNode, Node root) 
{ 
    // 1. if is has child, next is its first child 
    if (currentNode.getChildSize() > 0) { 
     return currentNode.getChildren()[0]; 
    } 
    // 2. if it has no child, check if its is the last child of his parent 
    else { 
     // if it is root and has no children, return null 
     if (currentNode == root) { 
      return null; 
     } 

     // else should have parent which is or under root; 
     Node parent = currentNode.getParent(); 
     int index = getIndex(currentNode); 

     if (!isLastofParent(currentNode)) { 
      // ----a. if not last, next is his parent's next 
      return currentNode.getParent().getChildren()[index + 1]; 
     } 
     else { 
      // ----b. if it is the last one, return its parent's next right if there is. while until root 
      Node tmp = parent; 
      while (tmp != root) { 
       int parentIndex = getIndex(tmp); 
       if (!isLastofParent(tmp)) { 
        return tmp.getParent().getChildren()[parentIndex + 1]; 
       } 
       tmp = tmp.getParent(); 
      } 
     } 
    } 
    return null; 

} 

private static boolean isLastofParent(Node node) 
{ 
    if (getIndex(node) == node.getParent().getChildSize() - 1) { 
     return true; 
    } 
    return false; 
} 

private static int getIndex(Node currentNode) 
{ 
    Node parent = currentNode.getParent(); 
    for (int i = 0; i < parent.getChildSize(); i++) { 
     if (parent.getChildren()[i] == currentNode) { 
      return i; 
     } 
    } 
    //TODO: error condition handling, will not happen if tree not change 
    return -1; 
} 

------------------------完全な検索がより簡単に............

です
public static Node getNextFailNode(Node currentNode, Node root, Condition condition) 
{ 
    boolean foundCurrentNode = false; 
    Stack<Node> stack = new Stack<Node>(); 
    stack.push(root); 
    while (!stack.isEmpty()) { 
     Node tmp = stack.pop(); 
     System.out.println("-popup---------" +tmp+ " "); 
     if (foundCurrentNode && checkCondition(tmp, condition)) { 
      return tmp; 
     } 
     if (tmp == currentNode) { 
      foundCurrentNode = true; 
     } 
     if (tmp.getChildSize() > 0) { 

      for (int i = tmp.getChildSize() - 1; i >= 0; i--) { 
       stack.push(tmp.getChildren()[i]); 
      } 
     } 

    } 
    return null; 
} 

答えて

0

これに必要なもののために多分道誇張が、それはあなたが望むものをサポートすることができます:Gremlin

グラフトラバーサル言語があります。通常、Neo4jのようなものの上にボルトで固定されていますが、APIをサポートするために任意のグラフデータ構造(例:単一ルート有向木)をラップすることができます。どのように完了したのか調べるにはBlueprintsプロジェクトを見てください。

[編集:以下の重何かのために]

おそらくJGraphTは、あなたが望むものです。またthis question on SOを見てください。それは正確な複製ではありませんが、それが役立つはずです。

+0

ありがとう、あまりにも重いです。 –

0

任意のノードから初期化できるツリーのイテレータを作成し、プリ/イン/ポストオーダートラバーサルを使用します(もちろん、双方向でなければなりません)。 これは基本的には少なくとも私にとっては簡単なアルゴリズムを書いています。 イテレータを取得したら、リーフである次のノードに向かって反復し、その条件が保持されるだけです。 特定の部分に問題がある場合は尋ねてください。私は自分の答えを改善します。

0

あなたがすでにインターフェースを定義しており、グラフ - トラバーサルライブラリがあまりにも重すぎると言えば、おそらくあなた自身で書くべきです。それは絶対に些細な量のコードでしょう。 (ヘルプが必要な場合はThis pageにコードが含まれています。)

(あなたのAPIの提案:Nodeにはboolean isRoot();メソッドを入れないでください。それは非常に正当な理由がない限り、ビットの無駄です。ツリーを構築するコードは、ルートノード)

+0

ありがとう、私はとても怠惰ではない:)昼食後にgetNextにメソッドを書く。 –

+0

@jkraybill:私はそこに置く。インターフェイスなので、ビットはありません。 – alphazero

関連する問題