C# 树状分支算法
我试图创建一个函数,输入是一个ID列表,输出是一个树,其中节点基于其C# 树状分支算法,c#,algorithm,C#,Algorithm,我试图创建一个函数,输入是一个ID列表,输出是一个树,其中节点基于其ID和所有父节点 每个节点都有一个父ID主页(ID:1)是根目录 函数标题类似于: public ModuleDTO GetModuleTree(List<int> ids); 提前感谢。(我假设这里的查找速度不是很重要,或者树比较小) 首先,让我们考虑为单个输入找到答案。这里一个可用的方法是尝试一个递归算法。查看树中的每个节点,找到后立即返回。一旦开始从递归返回,您将继续“向上”树,并将所有节点返回到主节点 有多
ID
和所有父节点
每个节点都有一个父ID
<代码>主页(ID:1)是根目录
函数标题类似于:
public ModuleDTO GetModuleTree(List<int> ids);
提前感谢。(我假设这里的查找速度不是很重要,或者树比较小)
首先,让我们考虑为单个输入找到答案。这里一个可用的方法是尝试一个递归算法。查看树中的每个节点,找到后立即返回。一旦开始从递归返回,您将继续“向上”树,并将所有节点返回到主节点
有多个ID的情况就变成了只做几次,然后合并所有结果
当然,根据性能需求和更改数据结构的自由度,可以对该算法进行一些改进,也可以采取其他方法。不过,它们可能没有上述解决方案的实现那么简单和清晰。我用以下方法解决了这个问题:
public ModuleDTO GetModulesForUser(string userName)
{
// Returns the list of IDs
var ids = ListOfUserModules(userName);
var modules = GetModuleTree(null);
var module = modules.First();
PruneTree(module, ids);
return module;
}
public List<ModuleDTO> GetModuleTree(ModuleDTO parentModule)
{
int? parentID = null;
if (parentModule != null)
{
parentID = parentModule.ID;
}
var childModules = _modules.All().Where(s => s.ParentID == parentID).Select(x => x.ToDTO());
List<ModuleDTO> modules = new List<ModuleDTO>();
foreach (var m in childModules)
{
m.ChildModules = GetModuleTree(m);
modules.Add(m);
}
return modules;
}
private void PruneTree(ModuleDTO root, List<int> ids)
{
for(int i = root.ChildModules.Count() - 1; i >= 0; i--)
{
PruneTree(root.ChildModules[i], ids);
if (root.ChildModules[i].ChildModules.Count == 0)
{
if (!ids.Contains(root.ChildModules[i].ID))
{
root.ChildModules.RemoveAt(i);
}
}
}
}
public ModuleDTO GetModulesForUser(字符串用户名)
{
//返回ID的列表
var id=ListOfUserModules(用户名);
var modules=GetModuleTree(null);
var module=modules.First();
PruneTree(模块,id);
返回模块;
}
公共列表GetModuleTree(ModuleToParentModule)
{
int?parentID=null;
if(parentModule!=null)
{
parentID=parentModule.ID;
}
var childModules=_modules.All()。其中(s=>s.ParentID==ParentID)。选择(x=>x.ToDTO());
列表模块=新列表();
foreach(childModules中的var m)
{
m、 ChildModules=GetModuleTree(m);
增加(m);
}
返回模块;
}
私有void PruneTree(模块化为根,列表ID)
{
对于(int i=root.ChildModules.Count()-1;i>=0;i--)
{
PruneTree(root.ChildModules[i],id);
if(root.ChildModules[i].ChildModules.Count==0)
{
如果(!ids.Contains(root.ChildModules[i].ID))
{
根.ChildModules.RemoveAt(i);
}
}
}
}
为什么输入时会返回2
?它不是4
的父项?您是正确的,已修复。很抱歉。:)你试过什么吗?我建议现在将其限制为一个数字(即不要尝试从5
和8
案例开始)。提示:递归深度优先搜索。我试过一些方法。主要是我很难决定是将分支添加到根节点(构建树),还是从一个完整的树开始并过滤掉节点。你有一个例子给我看吗?
public ModuleDTO GetModulesForUser(string userName)
{
// Returns the list of IDs
var ids = ListOfUserModules(userName);
var modules = GetModuleTree(null);
var module = modules.First();
PruneTree(module, ids);
return module;
}
public List<ModuleDTO> GetModuleTree(ModuleDTO parentModule)
{
int? parentID = null;
if (parentModule != null)
{
parentID = parentModule.ID;
}
var childModules = _modules.All().Where(s => s.ParentID == parentID).Select(x => x.ToDTO());
List<ModuleDTO> modules = new List<ModuleDTO>();
foreach (var m in childModules)
{
m.ChildModules = GetModuleTree(m);
modules.Add(m);
}
return modules;
}
private void PruneTree(ModuleDTO root, List<int> ids)
{
for(int i = root.ChildModules.Count() - 1; i >= 0; i--)
{
PruneTree(root.ChildModules[i], ids);
if (root.ChildModules[i].ChildModules.Count == 0)
{
if (!ids.Contains(root.ChildModules[i].ID))
{
root.ChildModules.RemoveAt(i);
}
}
}
}