我有一棵树(带复选框),如下所示。
A A1 A11 A111 (selected) A112 (selected) A113 B11 B111 (selected) B112
我想过滤此项以返回如下,因为A1
是所选节点的公共父级
A1 A11 A111 A112 B11 B111
树是具有根节点及其子节点的层次结构:
public class Node
{
public int Id;
public string Name;
public Node Parent;
public List<Node> Children;
}
基本上,这是UI中的树结构。根据用户选择的内容(复选框),我必须找到公共父级并显示结果树。
答案 0 :(得分:3)
这里是找到一组节点的共同祖先的基本思想:
那么,我们该怎么做呢?
让我们首先编写一个属性来获取Node
的祖先列表。 (我们需要&#34;和self&#34;部分来处理只选择一个节点的情况 - 在这种情况下,公共节点就是那个节点本身而我假设你没有想要父母。如果我错了并且你想让它找到父母,你可以改变这个属性只返回严格的祖先,但是你需要为根节点添加一个特殊情况,没有祖先。)
public List<Node> AncestorsAndSelf
{
get
{
List<Node> list = new List<Node> { this };
Node p = Parent;
while (p != null)
{
list.Add(p);
p = p.Parent;
}
return list;
}
}
System.Linq
命名空间中已有一个Intersect
方法可以找到一组项目的交集,因此我们已经覆盖了第2步。
对于第三步,我们需要一种方法来获取节点的深度。但是因为我们已经编写了AncestorsAndSelf
属性,所以这很简单:
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;
}
以下是展示整个行动的演示:https://dotnetfiddle.net/cl7JGp
答案 1 :(得分:0)
假设您有一个名为nodes
的根级节点列表,您可以这样做:
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