2009-05-19 9 views
1

私のプロジェクトでは再帰関数を書くことが多いことに気付きました。一般的な再帰関数の処理

私の質問です:再帰的反復を使用している各階層構造の汎用関数として再帰関数を作成する方法はありますか?

おそらく、再帰のルートと終了フラグを取得する代理人を使用できますか?

アイデア?

ありがとうございました。

+0

あなたはより具体的にする必要があるとしています。それを一般的にする方法があるかもしれませんが、私たちはより多くの情報なしでは手伝ってはいけません。 –

+1

genericiseを探しているコードサンプルはここで大きな助けになります。 – Lazarus

答えて

0

あなたの質問が何を求めているのかよく分かりませんが、再帰関数は一般的なものです。それに制限はありません。例えば:

int CountLinkedListNodes<T>(MyLinkedList<T> input) { 
    if (input == null) return 0; 
    return 1 + CountLinkedListNodes<T>(input.Next); 
} 
0

容易にし、また、一般的なアプローチは、関数の結果をキャッシュすることで、結果がわかっている場合にのみ、「本当の」機能を使用する可能性があります - このアプローチのeffectivnessはどのように頻繁に同じセットを依存しますあなたの再帰中に使用されます。

Perlを知っている場合は、最初の4つの章(Higher-Order Perl)をEBookとして利用できることを確認してください。提示されるアイデアは、言語に依存しません。

0

解決策がVisitor Patternを正常に使用できるように思えます。

Visitor Patternの特定のバリエーションを作成するには、hierarchical visitor patternを作成します。

完全にここで議論するのはちょっと複雑ですが、それであなたはいくつかの研究に着手する必要があります。基本的な考え方は、構造体をどのようにトラバースするかを知っているクラスがあり、次に特定のノードを処理する方法を知っているVisitorクラスがあることです。ノードの処理とツリーのトラバーサルを分けることができます。

1

私はあなたが望むのは、一般的な方法(英語で定義されている "ジェネリック"、必ずしも.Netで定義されているとは限らない)で階層構造を扱う方法だと思います。別の例

public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> selector) 
{ 
    if (items == null) 
     throw new ArgumentNullException("items"); 
    if (selector == null) 
     throw new ArgumentNullException("selector"); 

    return SelectManyRecursiveInternal(items, selector); 
} 

private static IEnumerable<T> SelectManyRecursiveInternal<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> selector) 
{ 
    foreach (T item in items) 
    { 
     yield return item; 
     IEnumerable<T> subitems = selector(item); 

     if (subitems != null) 
     { 
      foreach (T subitem in subitems.SelectManyRecursive(selector)) 
       yield return subitem; 
     } 
    } 
} 


// sample use, get Text from some TextBoxes in the form 
var strings = form.Controls 
        .SelectManyRecursive(c => c.Controls) // all controls 
        .OfType<TextBox>() // filter by type 
        .Where(c => c.Text.StartWith("P")) // filter by text 
        .Select(c => c.Text); 

:各CategoryControlControlsコレクションを持ってChildCategories(同じ方法を持っている可能性がCategoryクラスたとえば、これは私がWindowsフォーム内のすべてのコントロールを取得するために必要なときに、私は一度書いたものです)とrootCategoryが直接または間接的に全てのカテゴリーの親であると仮定:

// get all categories that are enabled 
var categories = from c in rootCategory.SelectManyRecursive(c => c.ChildCategories) 
       where c.Enabled 
       select c; 
1

私の質問は:のための一般的な機能として、再帰関数を作成するにはどのような方法がありますそれぞれの階層構造は反復的な反復を使用していますか? 私は再帰的なのルートと終了フラグを取得するデリゲートを使用することができますか?

はい - 必要なのは、各要素の子のリストを計算する代理関数だけです。子が返されない場合、関数は終了します。

delegate IEnumerable<TNode> ChildSelector<TNode>(TNode Root); 

    static IEnumerable<TNode> Traverse<TNode>(this TNode Root, ChildSelector<TNode> Children) { 
     // Visit current node (PreOrder) 
     yield return Root; 

     // Visit children 
     foreach (var Child in Children(Root)) 
      foreach (var el in Traverse(Child, Children)) 
       yield return el; 

    } 

例:

 static void Main(string[] args) { 

     var Init = // Some path 

     var Data = Init.Traverse(Dir => Directory.GetDirectories(Dir, "*", SearchOption.TopDirectoryOnly)); 

     foreach (var Dir in Data) 
      Console.WriteLine(Dir); 

     Console.ReadKey(); 
    } 
+0

+1 .Net 2.0ではデリゲート宣言が必要です。しかし、.Net 3.5+をターゲットにしている場合は、Func > – Lucas