递归 lambda 表达式通过有向图查找路径?

发布于 2024-07-10 17:05:12 字数 1170 浏览 8 评论 0原文

我需要在复杂的图形结构中找到一条或多条路径。 该图是使用类似以下内容构建的:

class Node
{
    public string Value { get; set;}
    public List<Node> Nodes { get; set;}

    public Node()
    {
        Nodes = new List<Node>();
    }
}

使事情变得复杂的是节点可以引用回较早的节点。 例如,

A-> C-> E->

我需要做的是获取一个堆栈列表,这些堆栈表示通过节点的路径,直到到达具有特定值的节点。 由于可能存在一些非常大的路径可用,因此我们可以尝试最多的节点。

List<Stack<Node>> paths = FindPaths(string ValueToFind, int MaxNumberNodes);

有谁有办法构建这个(或类似的东西)? 我过去曾做过递归,但出于某种原因,我在思考这个问题时脑子里全是放屁。 我的问题指定了 lambda 表达式,但不一定需要使用 lambda。 我将不胜感激任何解决方案。

旁注:我从 aku 对这个递归的优秀答案中提升了课程。问题。 虽然他下面显示的优雅的解决方案遍历了树结构,但它似乎没有足够的灵活性来完成我需要的操作(例如,忽略圆形路径并跟踪成功的路径)。

Action<Node> traverse = null;
traverse = (n) => { Console.WriteLine(n.Value); n.Nodes.ForEach(traverse);};
traverse(root);  // where root is the tree structure

编辑

根据下面的评论和答案的输入,我在 CodeProject 中找到了一个出色的解决方案。 它使用A*寻路算法。 这是链接。

I need to find a path or paths down a complicated graph structure. The graph is built using something similar to this:

class Node
{
    public string Value { get; set;}
    public List<Node> Nodes { get; set;}

    public Node()
    {
        Nodes = new List<Node>();
    }
}

What makes this complicated is that the nodes can reference back to an earlier node. For example,

A -> C -> E -> A

What I need to do is get a list of stacks which represent paths through the Nodes until I get to a Node with a specific value. Since its possible there can be some very large paths available we can have a maximum Nodes to try.

List<Stack<Node>> paths = FindPaths(string ValueToFind, int MaxNumberNodes);

Does anyone have a way to build this (or something similar)? I've done recursion in the past but I'm having a total brain fart thinking about this for some reason. My question specified a lambda expression but using a lambda is not necessarily required. I'd be grateful for any solution.

Side note: I lifted the class from aku's excellent answer for this recursion question. While his elegant solution shown below traverses the tree structure it doesn't seem to allow enough flexibility to do what I need (for example, dismiss paths that are circular and track paths that are successful).

Action<Node> traverse = null;
traverse = (n) => { Console.WriteLine(n.Value); n.Nodes.ForEach(traverse);};
traverse(root);  // where root is the tree structure

Edit:

Based on input from the comments and answers below I found an excellent solution over in CodeProject. It uses the A* path finding algorithm. Here is the link.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一刻暧昧 2024-07-17 17:05:12

如果您的问题与寻路有关,您可能需要在 google 上搜索“A star”或“A*”。
它是一种常见且高效的寻路算法。 有关与您的问题直接相关的示例,请参阅本文

您可能还想查看 Dijsktra 算法

If you're issue is related to Pathfinding, you may want to google for "A star" or "A*".
Its a common and efficient pathfinding algorithm. See this article for an example directly related to your problem.

You may also want to look at the Dijsktra Algorithm

甜是你 2024-07-17 17:05:12

我不确定您的预期输出是到达目标的所有路径、到达目标的最佳路径(通过某些指标,例如路径长度),还是只是 >任何实现目标的路径。

假设是后者,我将从递归策略开始,包括跟踪 Brann 概述的访问节点,并进行以下更改:

  1. 添加参数来表示正在寻求的目标、成功路径的集合以及当前路径添加

  2. 将当前路径(加上当前节点)添加到成功路径列表中。
  3. 使用当前节点扩展当前路径,以创建在任何递归调用上传递的路径。

    使用当前节点扩展

  4. 使用空路径和空的成功路径列表调用初始 ExploreGraph 调用。

完成后,您的算法将遍历整个图表,并且将捕获到达目标的不同路径。

这只是一个快速的草图,但您应该能够根据您的特定需求充实它。

I'm not sure whether your intended output is all paths to the goal, the best path to the goal (by some metric, e.g. path length), or just any path to the goal.

Assuming the latter, I'd start with the recursive strategy, including tracking of visited nodes as outlined by Brann, and make these changes:

  1. Add parameters to represent the goal being sought, the collection of successful paths, and the current path from the start.

  2. When entering a node that matches the goal, add the current path (plus the current node) to the list of successful paths.

  3. Extend the current path with the current node to create the path passed on any recursive calls.

  4. Invoke the initial ExploreGraph call with an empty path and an empty list of successful paths.

Upon completion, your algorithm will have traversed the entire graph, and distinct paths to the goal will have been captured.

That's just a quick sketch, but you should be able to flesh it out for your specific needs.

痞味浪人 2024-07-17 17:05:12

我不知道你到底想要实现什么,但是这个循环引用问题通常是通过标记已经访问过的节点来解决的。
只需使用字典来跟踪已经访问过的节点,这样就不会循环。

例子 :

  public void ExploreGraph(TreeNode tn, Dictionary<TreeNode, bool> visitednodes)
        {

            foreach (Treenode childnode in tn.Nodes)
            {
                if (!visitedNodes.ContainsKey(childnode))
                {
                    visitednodes.Add(childnode);
                    ExploreGraph(childnode, visitednodes);
                }
            }
        }

I don't know exactly what you want to achieve, but this circular reference problem is usually solved by tagging already visited nodes.
Just use a Dictionnary to keep track of the nodes which have already been visited so that you don't loop.

Example :

  public void ExploreGraph(TreeNode tn, Dictionary<TreeNode, bool> visitednodes)
        {

            foreach (Treenode childnode in tn.Nodes)
            {
                if (!visitedNodes.ContainsKey(childnode))
                {
                    visitednodes.Add(childnode);
                    ExploreGraph(childnode, visitednodes);
                }
            }
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文