2011-06-23 13 views
6

私はしばしば、階層オブジェクトのツリーを横断し、道に沿って各アイテムに対して操作を実行する必要があることがよくあります。この種の操作のための一般的に受け入れられている名前は、リストの理解であるか?私は、最初に覚えているから、Pythonのzip functionが、それが.netフレームワークに相当する前に覚えていて、珍しいが適切な名前を持っていると思っていたので、私は尋ねる。ここでこのタイプの列挙可能な操作に受け入れられる名前はありますか?

は、最大再帰一般化方法の、ツリー構造のダウンカップルであり、彼らが遭遇しているとして、各項目をもたらします。

public static IEnumerable<T> Ancestors<T>(T source, Func<T, T> selector) 
{ 
    do 
    { 
     yield return source; 
     source = selector(source); 
    } while (!Equals(source, default(T))); 
} 

public static IEnumerable<T> Descendents<T>(T source, 
              Func<T, IEnumerable<T>> selector) 
{ 
    var stack = new Stack<T>(); 
    stack.Push(source); 
    while (stack.Count > 0) 
    { 
     source = stack.Pop(); 
     yield return source; 
     var items = selector(source); 
     if (items != null) 
     { 
      foreach (var item in items) 
      { 
       stack.Push(item); 
      } 
     } 
    } 
} 
+0

何らかの種類のフィルタリングされたツリートラバーサル?これが特定の名前を持っているかどうかはわかりません。私はそれがあるとは思わない。 –

+0

2番目は深さ優先検索です。 2番目の名前には名前がありません。セレクタ関数に応じて 'Ancestors'と呼ばれますが、実際には 'parent'を実際に従う必要はありません(例えば、ノード) –

+0

@George:まさに「祖先」とはある種の階層関係を意味します。実際には、どちらの方向にもリンクされたリストを横断したり、任意の種類の任意のトレイルに従うのと同じように簡単に使用できます。 –

答えて

1

これらは、通常「ツリーウォーキング」とも呼ばれる標準Tree Traversalの機能です。具体的な歩行戦略がセレクタは子ノードを与え、あなたの第2の方法は、「最初の右の第1の深さ」トラバーサルであると仮定すると:)

7

を知られていないので、それはあなたの例で標準化された名前をつけることは困難です。それはあなたが

 A 
    /\ 
    B  C 
/\ /\ 
D E F G 

を持っていた場合は、 "第1の深さは、" それはできるだけ深く行くので、あなたが "B" の前にA、C、G、F、B、E、Dあなたが "G" を取得を取得し、あります別のブランチを試みる前に。あなたの特定の例では、Bの前にCが置かれます。なぜなら、左に右に優先順位を付けるからです。

あなたは

foreach (var item in items.Reverse()) 

にそれを変更した場合、あなたはほとんどの人が深さ優先トラバースを考える方法である左第一深さ優先探索を取得したいです。

あなたがキューにスタックを変更した場合、それは「幅優先」トラバーサルになります。 A、B、C、D、E、F、G.あなたは一度に "レベル"全体​​を行います。

他のトラバーサルもあります。深さ優先と幅優先検索には、親ノードが子ノードの前に来るという性質があります。すべてのノードがその子孫の後に来る「ポストオーダー」トラバーサルを持つこともできます。

バイナリツリーには、「インオーダ」トラバーサルもあります。このツリーのインオーダートラバーサルはD、B、E、A、F、C、Gです。つまり、すべての祖先はすべての祖先の前に来て、すべての児童はすべての祖先の後に来ます。練習問題として、バイナリツリーに順序通りのトラバーサルを書くことができますか?

+1

疑似コード運動のレスポンス: '関数Inorder(Tree){if(Tree == null){return;} Inorder(Tree.Left);出力(Tree.Value); Inorder(Tree.Right);} ' – Brian

+0

@Brian:Super。あなたは再帰なしでそれを行うことができますか? –

+0

@エリックでは、通常のスタック・スタックを使用してコール・スタックをエミュレートする必要があり、スタック上の各ノードにフラグを使用してリターン・アドレスをエミュレートする必要があります。スタックをポップすると、フラグをチェックして1.左に "再帰する"か、現在のノードを返す(収穫)か "再帰する"かをチェックします。基本的にテールコールの最適化である第3の状態は必要ありません。 – svick

関連する問題