我正在尝试创建一个函数,其中输入是ID列表,输出是基于ID
的节点的树所有父节点。
每个节点都有一个ParentID
。 Home
(ID:1)是根。
函数标题类似于:
public ModuleDTO GetModuleTree(List<int> ids);
示例树如下:
如果将4
传递给函数,它将返回如下树:
如果将5
和8
传递给函数,它将返回如下树:
如果将3
传递给函数,它将返回如下树:
我的课程如下:
public class ModuleDTO
{
public int ID { get; set; }
public string Name { get; set; }
public string TitleIS { get; set; }
public string TitleEN { get; set; }
public string RootURL { get; set; }
public int? ParentID { get; set; }
public List<ModuleDTO> ChildModules { get; set; }
public ModuleDTO()
{
ChildModules = new List<ModuleDTO>();
}
}
提前致谢。
答案 0 :(得分:1)
(我会假设查找速度在这里不重要,或树木适度小)
首先让我们考虑为单个输入找到答案。这里一个可用的方法是尝试depth-first type algorithm,一种递归算法。查看树中的每个节点,一旦找到它,就返回它。一旦从递归开始返回,您将继续“向上”树,并将所有节点返回到主节点。
有几个ID的情况就这样做了好几次,并加入了所有的结果。
当然,根据性能需求和更改数据结构的自由,可以对此算法以及可采取的其他方法进行一些改进。但是,它们可能不像上述解决方案的实现那么简单明了。
答案 1 :(得分:0)
我解决了这个问题:
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);
}
}
}
}