Большинство ответов, представленных здесь, производят последовательности в глубину или зигзагообразные последовательности. Например, начиная с дерева ниже:
1 2
/ \ / \
/ \ / \
/ \ / \
/ \ / \
11 12 21 22
/ \ / \ / \ / \
/ \ / \ / \ / \
111 112 121 122 211 212 221 222
dasblinkenlight в ответ производит эту сплющенную последовательность:
111, 112, 121, 122, 11, 12, 211, 212, 221, 222, 21, 22, 1, 2
Konamiman в ответ (что обобщается Эрик Липперта ответа ) производит эту сплюснутую последовательность:
2, 22, 222, 221, 21, 212, 211, 1, 12, 122, 121, 11, 112, 111
Ответ Ивана Стоева дает эту уплощенную последовательность:
1, 11, 111, 112, 12, 121, 122, 2, 21, 211, 212, 22, 221, 222
Если вы заинтересованы в широте первой последовательности , как это:
1, 2, 11, 12, 21, 22, 111, 112, 121, 122, 211, 212, 221, 222
... тогда это решение для вас:
public static IEnumerable<T> Flatten<T>(this IEnumerable<T> source,
Func<T, IEnumerable<T>> childrenSelector)
{
var queue = new Queue<T>(source);
while (queue.Count > 0)
{
var current = queue.Dequeue();
yield return current;
var children = childrenSelector(current);
if (children == null) continue;
foreach (var child in children) queue.Enqueue(child);
}
}
Разница в реализации в основном заключается в использовании Queue
вместо Stack
. Фактической сортировки не происходит.
Внимание: эта реализация далека от оптимальной с точки зрения эффективности использования памяти, поскольку большой процент от общего числа элементов в конечном итоге будет сохранен во внутренней очереди во время перечисления. Stack
обходы на основе дерева намного эффективнее с точки зрения использования памяти, чем Queue
реализации на основе.