因此,当访问节点时,您需要跟踪您在树中的位置。为了能够做到这一点,您需要引入某种上下文。
类似这样的:
public class VisitContext
{
// Visited node
public VisitedType Visited { get; set; }
// Visited node is the left child node
public bool IsLeftNode { get; set; }
// Visited node is the right child node
public bool IsRightNode { get; set; }
}
所以访客得到了这份合同:
public interface IVisitor
{
public void Visit(VisitContext context);
}
现在你只需要遍历它。关键是要有一个受保护的重载,告诉孩子他们是哪种类型。请注意递归调用。
public class VisitedType
{
public void Accept(IVisitor visitor)
{
var context = new VisitContext{ Visited = this };
visitor.Visit(context);
_leftNode.AcceptAsLeft(context);
_rightNode.AcceptAsRight(context);
}
protected void AcceptAsLeft(VisitContext context)
{
context.IsLeftNode=true;
context.IsRightNode=false;
visitor.Visit(context);
_leftNode.AcceptAsLeft(context);
_rightNode.AcceptAsRight(context);
}
protected void AcceptAsRight(VisitContext context)
{
context.IsLeftNode=false;
context.IsRightNode=true;
visitor.Visit(context);
_leftNode.AcceptAsLeft(context);
_rightNode.AcceptAsRight(context);
}
}
现在你知道你什么时候在树上左右移动了,但你仍然不知道你在树上的什么位置。为此,让我们引入一个 lineage/breadcrumbs 来跟踪我们当前的路径。
public class VisitContext
{
public VisitedType Visited { get; set; }
public bool IsLeftNode { get; set; }
public bool IsRightNode { get; set; }
// this.
public LinkedList<VisitedType> Lineage { get; set; }
}
并更新访问类型:
public class VisitedType
{
public void Accept(IVisitor visitor)
{
var context = new VisitContext{ Visited = this, Lineage = new LinkedList<VisitedType>() };
context.Lineage.AddLast(this);
visitor.Visit(context);
_leftNode.AcceptAsLeft(context);
_rightNode.AcceptAsRight(context);
}
protected void AcceptAsLeft(VisitContext context)
{
//add a bread crumb
context.Lineage.AddLast(this);
context.IsLeftNode=true;
context.IsRightNode=false;
visitor.Visit(context);
_leftNode.AcceptAsLeft(context);
_rightNode.AcceptAsRight(context);
//remove us when we've visited our children
context.Lineage.RemoveLast();
}
protected void AcceptAsRight(VisitContext context)
{
//add a bread crumb
context.Lineage.AddLast(this);
context.IsLeftNode=false;
context.IsRightNode=true;
visitor.Visit(context);
_leftNode.AcceptAsLeft(context);
_rightNode.AcceptAsRight(context);
//remove us when we've visited our children
context.Lineage.RemoveLast();
}
}
现在您应该能够通过层次结构跟踪访问。这要归功于递归调用,它会在遍历层次结构时继续构建面包屑。