树枝算法

时间:2013-10-29 21:39:26

标签: c# algorithm

我正在尝试创建一个函数,其中输入是ID列表输出是基于ID的节点的树所有父节点。

每个节点都有一个ParentIDHome(ID:1)是根。

函数标题类似于:

public ModuleDTO GetModuleTree(List<int> ids);

示例树如下:

  • 1家
    • 2个应用程序
    • 3教学
      • 4个课程
      • 5间客房
      • 6名教师
    • 7研究
      • 8出版物
    • 9毕业

如果将4传递给函数,它将返回如下树:

  • 1家
    • 3教学
      • 4个课程

如果将58传递给函数,它将返回如下树:

  • 1家
    • 3教学
      • 5间客房
    • 7研究
      • 8出版物

如果将3传递给函数,它将返回如下树:

  • 1家
    • 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>();
    }
}

提前致谢。

2 个答案:

答案 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);
            }
        }
    }
}