2012-02-03 20 views
9

私は、開始ルートノードが与えられていると、すべてのサブツリーノードを返す再帰関数を持っています。次のツリー構造についてはツリー内のyieldリターン要素の順序の再帰

private IEnumerable<Node> getAllNodesRecursively(Node subnode) 
{ 
    foreach (Node node in subnode.Nodes) 
     getAllNodesRecursively(node); 

    yield return subnode; 
} 

foreach (Node n in getAllNodesRecursively(a)) 
{ 
    Console.WriteLine(n); 
} 

関数は値を返します。

A 
| 
+--B 
| 
+--C 
| | 
| +--D 
| 
+--E 

私のような反復処理しようとし

再帰でyield-returnを使い、Preorder(この例ではA、B、C、D、E)の要素を検索したいと考えています。

(foreachの前にyield yieldを置くとforeachは起こりません)。

これは可能ですか?

+0

てみましたか?私はそれが呼ばれると思います。 – okrumnow

+0

はい、あなたは正しいです。 yield returnはコードの残りの部分をスキップしません。それは値の復帰を許しても機能を実行し続けるための文法的な砂糖のようだ。私の悪い。 –

答えて

16

はあなたのような何かを試してみましたあなたが前に降伏リターンを入れた場合のforeachが呼び出されていないことを

+0

これはうまくいきますが、なぜ私はもう一度繰り返す必要がありますか(内側foreach)?なぜイテレータメソッドは再帰をそのまま許可しないのですか?私はデバッガを試してみましたが、反復(foreachなど)で使用されていない限り、再帰呼び出しをスキップしました。何故ですか? –

+0

@ChristianHayter "トップノードを除くすべてのノードを2回返しませんか?" No. – Joe

+1

Joeの例は少し簡略化できます。private IEnumerable getAllNodesRecursively(ノードルート) { yield return root; foreach(root.Nodes.SelectMany(getAllNodesRecursively)の子var) { yield return child; } } – peter70

3

はい、可能です。ちょうどyield returnforeachの前に置いてください。あなたは通常のreturnステートメントの動作を考えています。あなたの実装では、再帰的にgetAllNodesRecursivelyを呼び出し、その戻り値を無視している

private IEnumerable<Node> getAllNodesRecursively(Node subnode) 
{ 
    // Return the parent before its children 
    yield return subnode; 

    foreach (Node node in subnode.Nodes) 
    { 
     foreach(Node n in getAllNodesRecursively(node)) 
     { 
      yield return n; 
     } 
    } 
} 

:。

+0

表示される内容が間違っていたので投稿を修正しました。最初の要素のみが返されます。 foreachの前にyield returnを置くと、同じことが起こります。どうして? –

+0

Hmmm。私は今自分自身でこれを試す立場にはない。デバッガでコードをステップ実行しようとしましたか? –

+0

デバッガは単に再帰呼び出しをスキップします。それは興味深いものです。 –

1
 public IEnumerable<int> preOrder(Node root) 
     { 
      if (root == null) 
       yield break; 

      yield return root.val; 

      if (root.left != null) 
       foreach (int i in preOrder(root.left)) 
        yield return i; 

      if (root.right != null) 
       foreach (int i in preOrder(root.right)) 
        yield return i; 
     } 
+0

このコードスニペットは問題を解決する可能性がありますが[説明を含めて](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)本当に品質を向上させるのに役立ちますあなたの投稿の将来読者の質問に答えていることを覚えておいてください。そうした人々はあなたのコード提案の理由を知らないかもしれません。 – lokusking