我有一棵树,如下所示。
A1 B1 B2 A2 A3 B3 A4 A5 C1 C2 C3 A6
我想过滤此内容以返回
A1 A2 A3 A4 A5 A6
基本思想是只返回A节点。我遇到的困难是在A2的情况下我想要丢弃B1并将A2拉到B2的水平
我正在使用c#树由节点列表
组成答案 0 :(得分:2)
你想进行深度搜索(递归)并消除不是A的节点,对吗?
我会在回来的路上删除节点,将子节点插入父节点(在当前节点的位置),然后在非A节点上删除此节点。
像这样的事情(简化的伪代码,在迭代时更改节点集合时必须小心等等):
void FilterNode(Node node) {
foreach (Node child in node.Children) {
FilterNode(child);
}
if (node.Type != NodeType.A) {
foreach (Node child in node.Children) {
node.Parent.InsertAfter(node, child);
}
node.Parent.RemoveNode(node);
}
}
答案 1 :(得分:2)
我将假设您的树结构如下所示:
class Node<T> {
public readonly T Value;
public readonly LinkedList<Node<T>> Children;
public readonly bool IsEmtpy;
public Node() {
IsEmpty = true;
}
public Node(T value, LinkedList<Node<T>> children) {
Value = value;
Children = children;
IsEmpty = false;
}
}
您可以使用单个深度优先搜索一次过滤树。
我通常发现在函数式语言中将这些算法原型化更容易,然后在需要时将它们转换为C#。这是F#代码:
type 'a tree = Nil | Node of 'a * 'a tree list
// val filter : ('a -> bool) -> 'a tree list -> 'a tree list
let rec filter f = function
| Node(value, children)::xs ->
if f value then Node(value, filter f children)::filter f xs
else (filter f children) @ filter f xs
| Nil::xs -> filter f xs
| [] -> []
let input =
Node("A1",
[ Node("B1",
[ Node("B2", []);
Node("A2",
[ Node("A3", []);
Node("B3", [ Node("A4", []) ]) ]) ]);
Node("A5", []);
Node("C1",
[ Node("C2",
[Node("C3", [ Node("A6", []) ]) ]) ]) ])
let expectedOutput =
Node("A1",
[ Node("A2",
[ Node("A3", []);
Node("A4", []) ]);
Node("A5", []);
Node("A6", []) ])
let actualOutput = [input] |> filter (fun value -> value.StartsWith("A")) |> List.head
let testPasses = expectedOutput = actualOutput
和F#输出:
val testPasses : bool = true
这是C#中的等效代码:
static LinkedList<Node<T>> Filter(Func<T, bool> predicate, IEnumerable<Node<T>> input) {
var res = new LinkedList<Node<T>>();
foreach(Node<T> node in input) {
if (!node.IsEmpty) {
if (predicate(node.Value)) {
res.AddLast(new Node(node.Value, Filter(predicate, node.Children));
else {
res.AddRange(Filter(predicate, node.Children));
}
}
}
return res;
}
答案 2 :(得分:1)
这是我在看到Lucero的解决方案之前提出的解决方案
private List<NodesEntity> ReturnHierarchyFilteredByType(List<NodesEntity> nodesEntities, List<String> nodeTypes)
{
List<NodesEntity> _nodesEntities = new List<NodesEntity>();
foreach (NodesEntity _nodesEntity in nodesEntities)
{
//We first recurse to the bottom
List<NodesEntity> _childNodesEntities = ReturnHierarchyFilteredByType(_nodesEntity.ChildNodes, nodeTypes);
if (nodeTypes.Contains(_nodesEntity.Type))
{
//The node matches what we have in the list
_nodesEntities.Add(_nodesEntity);
_nodesEntity.ChildNodes = _childNodesEntities;
}
else
{
//We pull the child nodes into this level
_nodesEntities.AddRange(_childNodesEntities);
}
}
return _nodesEntities;
}