Рекурсия в C # итератор - PullRequest
14 голосов
/ 17 ноября 2010

Можно ли использовать рекурсию в итераторе, реализующем System.Collections.IEnumerable?У меня есть древовидная структура, объявленная примерно так:

public class Node
{
    public Node Sibling;
    public Node Child;
}

Я бы хотел перебрать узлы в дереве.Я хотел бы сделать что-то вроде этого (псевдокод, я думаю, это не скомпилируется):

public class NodeIterator : System.Collections.IEnumerable
{
    Node m_root;

    public System.Collections.IEnumerator GetEnumerator()
    {
        recursiveYield(m_root);
    }

    System.Collections.IEnumeraton recursiveYield(Node node)
    {
        yield return node;
        if (node.Child)
        {
            recursiveYield(node.Child);
        }
        if (node.Sibling)
        {
            recursiveYield(node.Sibling);
        }
    }
}

Возможно ли это как-то?Я понимаю, что это можно решить без рекурсии, используя деку Node в функции GetEnumerator.

Ответы [ 2 ]

19 голосов
/ 17 ноября 2010

Да, все, что вам нужно, это перебрать возвращаемое значение с сайта вызова. Вот так:

IEnumerable<T> Recursive(Node node)
{
    yield return node;
    foreach (var siblingNode in Recursive(node.Sibling))
    {
        yield return siblingNode;
    }
    foreach (var childNode in Recursive(node.Child))
    {
        yield return childNode;
    }
}

Для записи, это не лучше, чем использовать очередь для достижения, например. обход в ширину. Требования к памяти для чего-то подобного в худшем случае идентичны.

3 голосов
/ 17 ноября 2010

Нет, потому что функция recursiveYield(Node node) вернет коллекцию, и вы можете получить только элемент

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...