別の方法として、再帰を使用して構造を平坦化することを検討できます。二分木の例を次に示します。これは、深さ優先の平坦化トラバーサルを示しています。
using System;
using System.Collections.Generic;
namespace Demo
{
public static class Program
{
static void Main(string[] args)
{
var tree = buildTree(5, true);
printTree1(tree);
Console.WriteLine("---------------------------------------------");
printTree2(tree);
}
// Print tree using direct recursion.
static void printTree1<T>(Node<T> tree)
{
if (tree != null)
{
Console.WriteLine(tree.Value);
printTree1(tree.Left);
printTree1(tree.Right);
}
}
// Print tree using flattened tree.
static void printTree2<T>(Node<T> tree)
{
foreach (var value in flatten(tree))
{
Console.WriteLine(value);
}
}
// Flatten tree using recursion.
static IEnumerable<T> flatten<T>(Node<T> root)
{
if (root == null)
{
yield break;
}
foreach (var node in flatten(root.Left))
{
yield return node;
}
foreach (var node in flatten(root.Right))
{
yield return node;
}
yield return root.Value;
}
static Node<string> buildTree(int depth, bool left)
{
if (depth > 0)
{
--depth;
return new Node<string>(buildTree(depth, true), buildTree(depth, false), "Node." + depth + (left ? ".L" : ".R"));
}
else
{
return new Node<string>(null, null, "Leaf." + (left ? "L" : "R"));
}
}
}
public sealed class Node<T>
{
public Node(Node<T> left, Node<T> right, T value)
{
_left = left;
_right = right;
_value = value;
}
public Node<T> Left { get { return _left; } }
public Node<T> Right { get { return _right; } }
public T Value { get { return _value; } }
private readonly Node<T> _left;
private readonly Node<T> _right;
private readonly T _value;
}
}
あなたの特定の例では、(テストせずに)これを行うことができると思います:
public static IEnumerable<Node> Flatten(Node root)
{
foreach (var node in root.Children)
{
foreach (var child in Flatten(node))
{
yield return child;
}
}
yield return root;
}
null ノードを許可するかどうかによっては、null チェックを追加する必要がある場合があります。
public static IEnumerable<Node> Flatten(Node root)
{
if (root != null)
{
foreach (var node in root.Children)
{
foreach (var child in Flatten(node))
{
if (child != null)
{
yield return child;
}
}
}
yield return root;
}
}