递归程序来获取节点的子级
本文关键字:节点 获取 程序 递归 | 更新日期: 2023-09-27 17:59:23
我有下表作为的示例
PNLId PNLCode PNLParentId Operator Sign
0
49 C 51 + NULL
50 Z 51 + NULL
51 Y 107 / NULL
52 B 107 / NULL
53 B 108 + NULL
我正在寻找关系父/子,所以我定义了以下类:
class Node {
public int Id { get; set; }
public int? ParentId { get; set; }
public string Operator { get; set; }
public string Sign { get; set; }
public Node Parent { get; set; }
public IList Children { get; set; }
public Node()
{
Children = new List<Node>();
}
public override string ToString()
{
//return "Node: " + Operator + " " + Id + " " + string.Join(",", Children.Select(x => x.Id));
return "Node: " + Operator + " " + Id + " "
+ string.Join(",", Children.Select(x => string.Format("({0}, {1})", x.Sign, x.Id)));
}
}
public void GetChild(Node node, Dictionary<int, Node> map, Dictionary<int, Node> mapf)
{
foreach (var child in node.Children)
{
foreach (var pairf in map)
{
if (child.Id == pairf.Value.ParentId)
{
child.Operator = pairf.Value.Operator;
var parent = map[pairf.Value.ParentId.Value];
child.Children.Add(pairf.Value);
mapf[child.Id] = map[pairf.Value.Id];
//rootNodes.Add(pairf.Value);
}
}
GetChild(child,map,mapf);
}
}
我已经成功地得到使用这个代码的根节点
var map = new Dictionary(); var rootNodes = new List();
foreach (DataRow row in dt.Rows)
{
int id = Convert.ToInt32(row["PNLId"]);
int? parentId = null;
if (!row.IsNull("PNLParentId"))
{
parentId = Convert.ToInt32(row["PNLParentId"]);
}
string op = Convert.ToString(row["Operator"]);
string sign = Convert.ToString(row["Sign"]);
map[id] = new Node
{
Id = id,
ParentId = parentId,
Operator = op,
Sign = sign
};
}
var mapf = new Dictionary<int, Node>();
// get rootnods
foreach (var pair in map)
{
if (pair.Value.ParentId.Equals(null))
{
mapf[pair.Value.Id] = map[pair.Value.Id];
rootNodes.Add(pair.Value);
}
}
// get operator for rootnods
foreach (var pair in mapf)
{
foreach (var pairf in map)
{
if (pair.Value.Id == pairf.Value.ParentId)
{
pair.Value.Operator = pairf.Value.Operator;
var parent = map[pairf.Value.ParentId.Value];
rootNodes.Add(pairf.Value);
GetChild(rootNodes., map, mapf);
}
}
}
我需要先构建节点树。然后从根节点开始从子节点复制运算符。前进到子级并复制其子级的运算符。例如
[92 Node: / 92 (, 36),(, 37)]
[93 Node: + 93 (, 38),(, 39),(, 40)]
[94 Node: / 94 (, 69),(, 70)]
[95 Node: + 95 (, 81),(, 82)]
[96 Node: + 96 (, 83),(, 84),(, 85),(, 86),(, 87),(, 88),(, 89)]
上面的代码没有返回此结果。如何修改?
从头开始:
public IEnumerable<Node> CreateTree(DataTable table)
{
var nodes = GetNodes(table).ToList();
var roots = new List<Node>();
foreach(var node in nodes)
{
if(node.ParentId==null)
roots.Add(node);
else
{
var parent = nodes.Single(n => n.Id == node.ParentId);
CreateRelationship(parent, node);
}
}
foreach (var root in roots)
{
UpdateOperators(root);
}
return nodes;
}
private void CreateRelationship(Node parent, Node child)
{
child.Parent = parent;
parent.Children.Add(child);
}
private IEnumerable<Node> GetNodes(DataTable table)
{
return from DataRow row in table.Rows select CreateNode(row);
}
private Node CreateNode(DataRow row)
{
return new Node
{
Id = Convert.ToInt32(row["PNLId"]),
ParentId = row.IsNull("PNLParentId") ? default(int?) : Convert.ToInt32(row["PNLParentId"]),
Operator = Convert.ToString(row["Operator"]),
Sign = Convert.ToString(row["Sign"])
};
}
private void UpdateOperators(Node parent)
{
if (!parent.Children.Any())
return;
parent.Operator = parent.Children.First().Operator;
foreach (var child in parent.Children)
{
UpdateOperators(child);
}
}
Node
应该保留代码中除了GetChild
方法之外的所有内容。此外,Children
应该声明为IList<Node>
,而不是IList
。
CreateTree
是您的入口点-它返回所有节点的IEnumerable
,整个树中的所有父/子关系都是正确的。