gpt4 book ai didi

c# - 与访客的抽象树

转载 作者:太空宇宙 更新时间:2023-11-03 10:46:14 25 4
gpt4 key购买 nike

我有非常简单的抽象类AbstractTree如下:

    public abstract class AbstractTree
{
public abstract void Accept(AbstractTreeVisitor visitor);
}

和两个具体类:带有左右 AbstractTree 字段的节点和带有整数值的 Leaf(+ 接受访问者的覆盖方法):

public class TreeNode : AbstractTree
{
public AbstractTree left;
public AbstractTree right;

public TreeNode(AbstractTree left, AbstractTree right)
{
this.left = left;
this.right = right;
}

public override void Accept(AbstractTreeVisitor visitor)
{
visitor.Visit(this);
}
}

public class TreeLeaf : AbstractTree
{
public int val;

public TreeLeaf(int val)
{
this.val = val;
}

public override void Accept(AbstractTreeVisitor visitor)
{
visitor.Visit(this);
}
}

现在我可以编写抽象访问者来访问我的树:

public abstract class AbstractTreeVisitor
{
public abstract void VisitNode(TreeNode n);
public abstract void VisitLeaf(TreeLeaf l);

public virtual void Visit(AbstractTree tree)
{
if (tree is TreeNode)
VisitNode((TreeNode)tree);
else
VisitLeaf((TreeLeaf)tree);
}
}

因此,让我们创建具体的访问者,它将计算叶中整数的总和:

public class SumTreeVisitor : AbstractTreeVisitor
{
int sum = 0;
public override void VisitNode(TreeNode n)
{
base.Visit(n.left);
base.Visit(n.right);
}

public override void VisitLeaf(TreeLeaf l)
{
sum += l.val;
}

public int GetSum()
{
return sum;
}
}

现在我可以在 main 中使用它了:

AbstractTree tree = new TreeNode(new TreeNode(new TreeLeaf(3), new TreeLeaf(4)), new TreeNode(new TreeLeaf(2),new TreeNode(new TreeLeaf(7),new TreeLeaf(3))));
SumTreeVisitor sum = new SumTreeVisitor();
tree.Accept(sum);
int i = sum.GetSum();
Console.WriteLine(i); //19

不过这位访客实在是太单纯了。

我的问题是,如何编写可以找到我的树的深度的访问者?当然,在伪代码中很容易,但我不知道如何将它写成 Visitor。在此先感谢您的帮助。

最佳答案

首先 - 你的 AbstractTree 不应该是一个类。它没有数据,也没有行为。它只是定义契约,所以它应该声明为接口(interface),例如

public interface ITreeNode
{
void Acept(ITreeVisitor visitor);
}

此外,您不需要在访问者类中使用不同名称的方法。如果参数类型不同,签名将不同。因此,您不需要 Visit 方法,并且您没有数据和行为,选择接口(interface):

public interface ITreeVisitor
{
void Visit(TreeNode node);
void Visit(TreeLeaf leaf);
}

现在 SumTreeVisitor - 您应该只接受节点上的当前访问者,调用将被分派(dispatch)给访问者的适当方法:

public class SumTreeVisitor : ITreeVisitor
{
public override void Visit(TreeNode node)
{
node.Left.Accept(this); // left and right should be properties
mode.Right.Accept(this);
}

public override void Visit(TreeLeaf leaf)
{
Sum += leaf.Value;
}

public int Sum { get; private set; }
}

请记住使用属性而不是公共(public)字段(您可以使用自动实现的属性):

public class TreeNode : ITreeNode
{
public ITreeNode Left { get; private set; }
public ITreeNode Right { get; private set; }

public TreeNode(ITreeNode left, ITreeNode right)
{
Left = left;
Right = right;
}

public void Accept(ITreeVisitor visitor)
{
visitor.Visit(this);
}
}

并且计算深度很简单 - 只需在访问下一个节点之前增加当前深度,并在访问后立即减少它:

public class DepthTreeVisitor : ITreeVisitor
{
private int _currentDepth = -1;

public void Visit(TreeNode node)
{
_currentDepth++;
node.Left.Accept(this);
node.Right.Accept(this);
_currentDepth--;
}

public void Visit(TreeLeaf leaf)
{
_currentDepth++;
if (_currentDepth > Depth)
Depth = _currentDepth;
_currentDepth--;
}

public int Depth { get; private set; }
}

通过测试:

ITreeNode root = new TreeNode(
new TreeNode(new TreeLeaf(3), new TreeLeaf(4)),
new TreeNode(new TreeLeaf(2),
new TreeNode(new TreeLeaf(7), new TreeLeaf(3)))
);

var visitor = new DepthTreeVisitor();
root.Accept(visitor);
visitor.Depth.Should().Be(3);

关于c# - 与访客的抽象树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23321669/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com