Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取具有特定id的节点的路径_C#_Algorithm_Recursion_Search - Fatal编程技术网

C# 获取具有特定id的节点的路径

C# 获取具有特定id的节点的路径,c#,algorithm,recursion,search,C#,Algorithm,Recursion,Search,我在解决一个看起来很简单的任务时遇到了严重的问题 我有一个基于复合模式的对象层次结构。对象如下所示: public class Org { public string Id; public string Name; public List<Org> Orgs; } 预期的结果是这样的 Org7 bmd --> Org1,Org3,Org7 Org2 cvf --> Org1,Org2 Org4 uyk --> Org1,Org3,Org4 请注意,O

我在解决一个看起来很简单的任务时遇到了严重的问题

我有一个基于复合模式的对象层次结构。对象如下所示:

public class Org
{
  public string Id;
  public string Name;
  public List<Org> Orgs;
}
预期的结果是这样的

Org7 bmd --> Org1,Org3,Org7
Org2 cvf --> Org1,Org2
Org4 uyk --> Org1,Org3,Org4
请注意,Org4不是叶节点

我可以找到很多关于搜索二叉树的解决方案,但在遍历层次结构时,我很难跟踪我的“当前节点”——特别是在搜索例如“Org5(suf)”时从Org2切换到Org3

任何帮助都将不胜感激

:-)

解决方案:

我在@Funk的建议中添加了一个小小的修改-现在对我有效:-)

静态void TraversePathToId(LookupTableItem组织、字符串id、列表路径)
{
如果(org.Id==Id)
{
path.Add(org.Name);
}
其他的
{
foreach(org.ChildItems中的变量child)
{
TraversePathToId(子项、id、路径);
if(path.Any())
{
path.Add(org.Name);
打破
}
}
}
}
静态列表GetPath(LookupTableItem根,字符串id)
{
列表路径=新列表();
TraversePathToId(根、id、路径);
path.Reverse();
返回路径;
}

BFS或DFS将完成这项工作。 您可以保留一个ID的全局数组来标记已访问的组织,当您到达一个对象时,可以对未访问的对象递归调用搜索。
要获取路径,请使用回溯。BFS或DFS将完成此任务。 您可以保留一个ID的全局数组来标记已访问的组织,当您到达一个对象时,可以对未访问的对象递归调用搜索。
要获得路径,请使用backtrack。

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

类程序
{
静态void TraversePathToId(组织、字符串id、列表路径)
{
if(org.Id==Id)path.Add(org.Name);
foreach(org.Orgs中的变量子项)
{
TraversePathToId(子项、id、路径);
if(path.Any())
{
path.Add(org.Name);
打破
}
}
}
静态列表GetPath(组织根,字符串id)
{
列表路径=新列表();
TraversePathToId(根、id、路径);
path.Reverse();
返回路径;
}
静态void Main(字符串[]参数)
{
组织根=新组织(“组织1”、“abc”)
{
Orgs=新列表
{
新组织(“Org2”、“cvf”),
新组织(“Org3”、“grf”)
{
Orgs=新列表
{
新组织(“Org4”、“uyk”)
{
Orgs=新列表
{
新组织(“Org5”、“suf”),
}
},
新组织(“Org6”、“vxl”),
新组织(“Org7”、“bmd”),
}
},
新组织(“Org8”、“pes”),
}
};
GetPath(root,“suf”).ForEach(name=>Console.Write($“{name}\t”);
Console.ReadLine();
}
}
公共类组织
{
公共组织(字符串名称、字符串id)
{
名称=名称;
Id=Id;
Orgs=新列表();
}
公共字符串名称{get;}
公共字符串Id{get;}
公共列表组织{get;set;}
}

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

类程序
{
静态void TraversePathToId(组织、字符串id、列表路径)
{
if(org.Id==Id)path.Add(org.Name);
foreach(org.Orgs中的变量子项)
{
TraversePathToId(子项、id、路径);
if(path.Any())
{
path.Add(org.Name);
打破
}
}
}
静态列表GetPath(组织根,字符串id)
{
列表路径=新列表();
TraversePathToId(根、id、路径);
path.Reverse();
返回路径;
}
静态void Main(字符串[]参数)
{
组织根=新组织(“组织1”、“abc”)
{
Orgs=新列表
{
新组织(“Org2”、“cvf”),
新组织(“Org3”、“grf”)
{
Orgs=新列表
{
新组织(“Org4”、“uyk”)
{
Orgs=新列表
{
新组织(“Org5”、“suf”),
}
},
新组织(“Org6”、“vxl”),
新组织(“Org7”、“bmd”),
}
},
新组织(“Org8”、“pes”),
}
};
GetPath(root,“suf”).ForEach(name=>Console.Write($“{name}\t”);
Console.ReadLine();
}
}
公共类组织
{
公共组织(字符串名称、字符串id)
{
名称=名称;
Id=Id;
Orgs=新列表();
}
公共字符串名称{get;}
公共字符串Id{get;}
公共列表组织{get;set;}
}
Hi@Funk,谢谢:-)。。。但它并不完全有效。它适用于叶节点,但对于非叶节点,它会在迭代任何子节点时乘以已标识的节点。问题是它在找到匹配项时添加了一个节点,但仍然遍历所有子节点。。。无论是否找到任何匹配项,都会执行path.any()操作,从而添加任何后续节点
Org7 bmd --> Org1,Org3,Org7
Org2 cvf --> Org1,Org2
Org4 uyk --> Org1,Org3,Org4
static void TraversePathToId(LookupTableItem org, string id, List<string> path)
{
    if (org.Id == id)
    {
        path.Add(org.Name);
    }
    else
    {
        foreach (var child in org.ChildItems)
        {
            TraversePathToId(child, id, path);
            if (path.Any())
            {
                path.Add(org.Name);
                break;
            }
        }
    }
}

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

    return path;
}
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; }
}