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