我经常发现自己需要遍历分层对象的树,并在整个过程中对每个项目执行操作。在列表理解白话中,这种操作是否有一个普遍接受的名称?我问,因为我记得在.net框架中有一个等价物并且认为它有一个不寻常但恰当的名称之前,首先要了解python的zip function。
以下是一些通用的方法,可以在树形结构中上下移动,并在遇到每个项目时生成它们。
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 :(得分:7)
假设选择器给出了子节点,你的第二种方法是“正确的第一个深度优先”遍历。也就是说,如果你有
A
/ \
B C
/ \ / \
D E F G
然后你得到A,C,G,F,B,E,D。你在“B”之前得到“G”,因为“深度优先”在它尝试另一个分支之前会尽可能地深入。在你的特定例子中,你会在B之前得到C,因为它优先于左边。
如果您将其更改为
foreach (var item in items.Reverse())
然后你会得到一个左先深度优先遍历,这是大多数人对深度优先遍历的看法。
如果您将堆栈更改为队列,那么它将成为“广度优先”遍历。 A,B,C,D,E,F,G。你一次做一整个“水平”。
还有其他遍历。请注意,深度优先和广度优先搜索都具有父节点位于子节点之前的属性。您还可以进行“后期订单”遍历,其中每个节点都在其子节点之后。
二叉树也有“顺序”遍历。这棵树的顺序遍历是D,B,E,A,F,C,G。也就是说,每个左边的孩子都来自它的所有祖先,每个正确的孩子都来自它的祖先。作为练习,你能在二叉树上编写有序遍历吗?
答案 1 :(得分:1)
这些是标准Tree Traversal函数,通常也称为“树行走”。很难给出你的例子标准名称,因为具体的步行策略是未知的:)