Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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# 如何将树筛选到公共父级_C#_Algorithm - Fatal编程技术网

C# 如何将树筛选到公共父级

C# 如何将树筛选到公共父级,c#,algorithm,C#,Algorithm,我有一个树(带有复选框),如下所示 A A1 A11 A111 (selected) A112 (selected) A113 B11 B111 (selected) B112 树是具有根节点及其子节点的层次结构: public class Node { public int Id; public string Name;

我有一个树(带有复选框),如下所示

A A1 A11 A111 (selected) A112 (selected) A113 B11 B111 (selected) B112 树是具有根节点及其子节点的层次结构:

public class Node
{
  public int Id;
  public string Name;
  public Node Parent;
  public List<Node> Children;
}
公共类节点
{
公共int Id;
公共字符串名称;
公共节点父节点;
公开儿童名单;
}

基本上,这是UI中的树结构。根据用户选择的内容(复选框),我必须找到公共父节点并显示结果树。

假设您有一个名为
节点的根级别节点列表,您只需执行以下操作:

var node = nodes.SingleOrDefault(_ => _.Name == "A1");
if (null != node)
    return node.Children;
return new List<Node>(); 
// or you can return null if you'd prefer
var node=nodes.SingleOrDefault(=>;
if(null!=节点)
返回节点。子节点;
返回新列表();
//如果愿意,也可以返回null

以下是查找一组节点的共同祖先的基本思想:

public static Node FindClosestCommonAncestor(IEnumerable<Node> selectedNodes)
{
    IEnumerable<Node> commonAncestors = selectedNodes.First().AncestorsAndSelf;
    foreach (Node n in selectedNodes.Skip(1))
    {
        commonAncestors = commonAncestors.Intersect(n.AncestorsAndSelf);
    }
    return commonAncestors.OrderByDescending(n => n.Depth).FirstOrDefault();
}
  • 对于每个选定节点,获取节点集,包括其自身及其祖先
  • 找到所有这些节点的交点
  • 其中,以深度最高的节点为例
  • 那么,我们如何做到这一点呢

    让我们首先编写一个属性来获取
    节点的祖先列表。(我们需要“和自我”部分来处理仅选择单个节点的情况——在这种情况下,公共节点是该节点本身,我假设您不想要父节点。如果我错了,您希望它找到父节点,您可以更改此属性以仅返回严格的祖先节点,但接下来您需要为根节点添加一个特殊情况,即没有祖先。)

    现在我们有了所有的部分,我们可以编写一个方法来查找选定节点集的共同祖先:

    public static Node FindClosestCommonAncestor(IEnumerable<Node> selectedNodes)
    {
        IEnumerable<Node> commonAncestors = selectedNodes.First().AncestorsAndSelf;
        foreach (Node n in selectedNodes.Skip(1))
        {
            commonAncestors = commonAncestors.Intersect(n.AncestorsAndSelf);
        }
        return commonAncestors.OrderByDescending(n => n.Depth).FirstOrDefault();
    }
    

    下面是一个演示,演示了整个过程:

    这不起作用,我必须根据在叶级别选择的内容找到一个
    公共
    父节点。它不是基于名称“A1”(“A1”只是一个用于说明的名称,我甚至不知道“A1”是常见的父项,我必须根据用户选择的内容“查找”它。我错过了“已选择的”你问题的一部分。我当时认为这是一个非常容易问的问题。Joel在软件博客上发表了一篇关于树结构以及他们如何管理任务树并保持其性能的老文章。我会看看是否能找到它,因为这是一个非常优雅的解决方案,使用节点的ID,你可以ind有用。从发布的树层次结构/节点类中,子节点没有对父节点的引用。如果是这种情况,则必须递归搜索父节点和所有子节点以查找所选节点,假设节点上有一些字段/属性将其标识为所选;可能会标识其所有select的分支深度ed节点,然后使用最高深度-1查找父节点。@MetroSmurf Pl查看我编辑的类。“公共父节点”的度量是什么?对我来说,应该是“A”,因为它们都属于A--你是如何找到“A1”的?它是直接的公共父节点
    public int Depth
    {
        get { return AncestorsAndSelf.Count; }
    }
    
    public static Node FindClosestCommonAncestor(IEnumerable<Node> selectedNodes)
    {
        IEnumerable<Node> commonAncestors = selectedNodes.First().AncestorsAndSelf;
        foreach (Node n in selectedNodes.Skip(1))
        {
            commonAncestors = commonAncestors.Intersect(n.AncestorsAndSelf);
        }
        return commonAncestors.OrderByDescending(n => n.Depth).FirstOrDefault();
    }
    
    public override string ToString()
    {
        return ToString("");
    }
    
    private string ToString(string indent)
    {
        string s = indent + Name + "\r\n";
        foreach (Node child in Children)
        {
            s += child.ToString(indent + "    ");
        }
        return s;
    }