获取具有特定ID的节点的路径

时间:2019-06-02 16:52:00

标签: c# algorithm recursion search

我遇到了严重的问题,无法解决从偏移量来看似乎很简单的任务。

我有一个基于复合模式的对象层次结构。这些对象看起来像这样:

public class Org
{
  public string Id;
  public string Name;
  public List<Org> Orgs;
}

我需要找到一个带有特定Org的{​​{1}}元素,并将路径返回到Id对象。

层次结构不是二叉树-每个Org对象可以有零个或多个子Org

所以如果层次结构是这个

Org

期望的结果是这样

Org1 (abc)
  Org2 (cvf)
  Org3 (grf)
    Org4 (uyk)
      Org5 (suf)
    Org6 (vxl)
    Org7 (bmd)
  Org8 (pes)

请注意,Org4不是叶节点。

我在搜索二叉树时可以找到很多解决方案,但是遍历层次结构时很难跟踪“当前节点”-特别是在从eg.arch中从Org2切换到Org3时。 “ Org5(suf)”。

任何帮助将不胜感激。

:-)

解决方案:

我对@Funk的建议做了一个小修改-现在对我有用:-)

Org7 bmd --> Org1,Org3,Org7
Org2 cvf --> Org1,Org2
Org4 uyk --> Org1,Org3,Org4

2 个答案:

答案 0 :(得分:1)

BFS或DFS将完成此工作。 您可以保留一个ID的全局数组,以标记访问过的组织,当您到达某个对象时,对未访问的对象进行递归搜索。 要获取路径,请使用回溯。

答案 1 :(得分:1)

具有递归的主要问题是,对于当前节点,您始终处在调用堆栈的顶部。在所有先前(父)节点处于较低级别的情况下,等待执行返回。这意味着您可以将结果传回给他们。并一次性确定路径(相反顺序)。

class Program
{
    static void TraversePathToId(Org org, string id, List<string> path)
    {
        if (org.Id == id) path.Add(org.Name);

        foreach (var child in org.Orgs)
        {
            TraversePathToId(child, id, path);
            if (path.Any())
            {
                path.Add(org.Name);
                break;
            }
        }
    }

    static List<string> GetPath(Org root, string id)
    {
        List<string> path = new List<string>();
        TraversePathToId(root, id, path);
        path.Reverse();

        return path;
    }

    static void Main(string[] args)
    {
        Org root = new Org("Org1", "abc")
        {
            Orgs = new List<Org>
            {
                new Org("Org2", "cvf"),
                new Org("Org3", "grf")
                {
                    Orgs = new List<Org>
                    {
                        new Org("Org4", "uyk")
                        {
                            Orgs = new List<Org>
                            {
                                new Org("Org5", "suf"),
                            }
                        },
                        new Org("Org6", "vxl"),
                        new Org("Org7", "bmd"),
                    }
                },
                new Org("Org8", "pes"),
            }
        };

        GetPath(root, "suf").ForEach(name => Console.Write($"{name}\t"));

        Console.ReadLine();
    }
}

public class Org
{
    public Org(string name, string id)
    {
        Name = name;
        Id = id;
        Orgs = new List<Org>();
    }
    public string Name { get; }
    public string Id { get; }
    public List<Org> Orgs { get; set; }
}