/// <summary> /// 判断节点是否是指定节点的后代节点 /// </summary> /// <typeparam name="T">节点数据类型</typeparam> /// <param name="node">待判断的节点</param> /// <param name="target">目标节点</param> /// <returns>判断结果</returns> public static bool IsDescendantOf <T>(this IHierarchical <T> node, IHierarchical <T> target) { if (node.Root != target.Root) { throw new InvalidOperationException($"{nameof(node)} and {nameof(target)} are not at same tree."); } return(target.IsAncestorOf(node)); }
/// <summary> /// 获取从指定节点到当前节点的路径 /// </summary> /// <typeparam name="T">节点数据类型</typeparam> /// <param name="node">当前节点(终点)</param> /// <param name="from">目标节点(起点)</param> /// <returns>按从目标节点到当前节点顺序经过的节点集合</returns> public static IEnumerable <IHierarchical <T> > GetPathFromNode <T>(this IHierarchical <T> node, IHierarchical <T> from) { if (node.Root != from.Root) { throw new InvalidOperationException($"{nameof(node)} and {nameof(from)} are not at same tree."); } yield return(from); //起点必然是需要的 if (node == from) { yield break; //如果终点就是起点,那么可以直接结束路径查找了 } //只有终点和起点不存在双亲孩子关系时才需要执行内部代码,否则直接返回终点即可 if (!(node.Parent == from || node.Children.Any(n => n == from))) { var nearestCommonAncestor = node.GetNearestCommonAncestor(from); //如果起点不是终点的祖先,需要先返回从起点的双亲到最近公共祖先 //(不包括最近公共祖先。最近公共祖先可能就是终点,返回的话会导致终点被返回两次。终点会在方法末尾统一返回)的路径 if (!from.IsAncestorOf(node)) { foreach (var ancestor in from.Ancestors) { if (ancestor != nearestCommonAncestor) { yield return(ancestor); } else { break; } } } //如果最近公共祖先不是终点,返回从最近公共祖先到终点(不包括终点,原因不再赘述)的路径 if (nearestCommonAncestor != node) { var ancestorsOfNode = node.Ancestors.ToArray(); for (int i = Array.IndexOf(ancestorsOfNode, nearestCommonAncestor); i >= 0; i--) { yield return(ancestorsOfNode[i]); } } } yield return(node); //最后返回终点 }
/// <summary> /// 获取节点与指定节点的最近公共祖先节点 /// </summary> /// <typeparam name="T">节点数据类型</typeparam> /// <param name="node">待查找的节点</param> /// <param name="target">目标节点</param> /// <returns>最近的公共祖先节点</returns> public static IHierarchical <T> GetNearestCommonAncestor <T>(this IHierarchical <T> node, IHierarchical <T> target) { if (node.Root != target.Root) { throw new InvalidOperationException($"{nameof(node)} and {nameof(target)} are not at same tree."); } if (node.IsAncestorOf(target)) { return(node); } if (target.IsAncestorOf(node)) { return(target); } return(node.Ancestors.Intersect(target.Ancestors).OrderByDescending(no => no.Level).First()); }
/// <summary> /// 获取从指定节点到当前节点的路径 /// </summary> /// <typeparam name="T">节点数据类型</typeparam> /// <param name="node">当前节点(终点)</param> /// <param name="from">目标节点(起点)</param> /// <returns>按从目标节点到当前节点顺序经过的节点集合</returns> public static IEnumerable <IHierarchical <T> > GetPathFromNode <T>(this IHierarchical <T> node, IHierarchical <T> from) { if (node.Root != from.Root) { throw new InvalidOperationException($"{nameof(node)} and {nameof(from)} are not at same tree."); } yield return(from); if (node == from) { yield break; } if (node.IsAncestorOf(from)) { foreach (var ancestor in from.Ancestors) { yield return(ancestor); if (ancestor == node) { yield break; } } } var ancestorsOfNode = node.Ancestors.ToArray(); if (node.IsDescendantOf(from)) { for (int i = Array.IndexOf(ancestorsOfNode, from) - 1; i >= 0; i--) { yield return(ancestorsOfNode[i]); } yield return(node); yield break; } var keyNode = ancestorsOfNode.Intersect(from.Ancestors).OrderByDescending(no => no.Level).First(); foreach (var ancestor in from.Ancestors) { yield return(ancestor); if (ancestor == keyNode) { break; } } for (int i = Array.IndexOf(ancestorsOfNode, keyNode) - 1; i >= 0; i--) { yield return(ancestorsOfNode[i]); } yield return(node); }