Вот основная идея для нахождения общего предка набора узлов:
- Для каждый выбранный узел, получает множество узлов, включая себя и своих предков;
- Найти перекресток всех этих узлов;
- Из них возьмите узел с наивысшей глубиной.
Итак, как мы это сделаем?
Начнем с написания имущества, чтобы получить список предков для Node
. (Нам нужна часть «и сам», чтобы обрабатывать ситуацию, когда выбран только один узел - в этом случае общий узел - это сам узел, и я предполагаю, что вы не хотите родителя. Если я ошибаюсь и вы хотите, чтобы найти родителей в любом случае, вы можете изменить это свойство возвращать только строгие предков, но тогда вам нужно добавить специальный случай для корневого узла, который не имеет предков.)
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
Из класса иерархии/Node Tree размещен, дочерний узел не имеет никакого отношения к родитель.Если это так, то вам придется рекурсивно искать родительский узел и всех дочерних элементов для поиска выбранных узлов, предполагая, что на узле есть определенное поле/свойство, идентифицирующее его как выбранное; возможно, идентифицируя глубину их всех выбранных узлов, а затем используя самую высокую глубину - 1, чтобы найти родительский узел. –
@MetroSmurf Pl посмотри мой отредактированный класс. –
Каковы показатели для «общего родителя»? Для меня это должно быть «А», так как все они подпадают под А - как вы попали в «А1» –