递归程序来获取节点的子级

本文关键字:节点 获取 程序 递归 | 更新日期: 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,整个树中的所有父/子关系都是正确的。