我在SO上发现了this关于C#中树实现的问题。我不知道代表,我想知道如何使用以下代码来实现树。另外,保持跟踪父节点的最有效方法是什么?
delegate void TreeVisitor<T>(T nodeData);
class NTree<T>
{
T data;
LinkedList<NTree<T>> children;
public NTree(T data)
{
this.data = data;
children = new LinkedList<NTree<T>>();
}
public void addChild(T data)
{
children.AddFirst(new NTree<T>(data));
}
public NTree<T> getChild(int i)
{
foreach (NTree<T> n in children)
if (--i == 0) return n;
return null;
}
public void traverse(NTree<T> node, TreeVisitor<T> visitor)
{
visitor(node.data);
foreach (NTree<T> kid in node.children)
traverse(kid, visitor);
}
}
答案 0 :(得分:3)
delegate
基本上可以让你谈论符合某些标准的任意函数,而不必确切地知道你正在谈论的函数。
考虑以下代码遍历树,并对每个元素执行操作:
void DoSomethingToAllNodes(NTree<T> node)
{
DoSomething(node);
foreach (var child in node.Children)
DoSomethingToAllNodes(child);
}
它有效,但它非常不灵活。我们必须为我们想要在节点上执行的每个不同操作重新实现该方法:
void DoSomethingElseToAllNodes(NTree<T> node)
{
DoSomethingElse(node);
foreach (var child in node.Children)
DoSomethingElseToAllNodes(child);
}
相反,我们可以声明一个委托来表示“任何一个NTree<T>
作为参数,并且不返回任何内容的方法”,然后我们可以接受一个满足该参数的方法。然后,我们可以实现一个处理所有可能性的单Traverse
方法,而不必为每个不同的操作重新实现它。
答案 1 :(得分:1)
如果你完全熟悉c或c ++,可以将委托视为类型安全的函数指针。这就是我如何设法了解代表与大多数人进行对话的想法。
答案 2 :(得分:0)
您的代码所做的是声明delegate
,它基本上是方法的签名。 traverse()方法接受任何函数,其签名与您声明为参数的委托匹配并调用它。为了娱乐和愉悦,一切都是通用的,以便启动。
delegate void TreeVisitor<T>(T nodeData);
// This function takes a handle to a method as a parameter,
// and invokes that method for each node
public void traverse(NTree<T> node, TreeVisitor<T> visitor) {
visitor(node.data);
...
}
可以像:
一样调用public class MyEvilPlans {
public void WreakHavoc<int>(int nodeData) {
Console.WriteLine("The secret to life is: {0}", nodeData.ToString());
}
public void PlayWithTree() {
NTree<int> tree = new NTree<int>();
// Initialize tree
// If the tree has 47 nodes, WreakHavoc will be called 47 times,
// once for each node in the tree.
tree.traverse(WreakHavoc);
}
}
访问者模式允许您决定要为树的每个节点执行哪些代码...其他人控制树的实现,但您通过预定义的合同(委托)控制对树行为的响应。在某种程度上,它打破了封装,因为你知道你正在调用的方法的内部细节:它将为每个节点回调你。但这就是访客模式的全部内容:)
要回答问题的第二部分,如何跟踪父节点......你所拥有的是非二叉树。为了能够从任何节点遍历树,你必须给每个NTree一个NTree类型的成员称为'parent'。这应该由NTree的构造函数设置,以便您拥有:
// Added the handle to 'this'
children.AddFirst(new NTree<T>(data, this));
您可以找到关于非二叉树here的精彩讨论。