【问题标题】:How to re factor this c# tree population method to avoid using recursion [duplicate]如何重新考虑这个c#树填充方法以避免使用递归[重复]
【发布时间】:2013-03-27 14:26:21
【问题描述】:

下面的代码有效,但我想避免使用递归。 ListOfAllNodes 是数据库中所有节点的平面列表,包含 Id 和 ParentId 字段。

private Node FillChildNodes(Node node)
{
   foreach (var childNode in ListOfAllNodes.Where(i => i.ParentId == node.Id).OrderBy(x => x.Name))
   {
           node.Children.Add(childNode);
           FillChildNodes(childNode);
   }
   return node;
}

【问题讨论】:

  • 为什么要避免递归?递归并不邪恶!在某些情况下使用它是有意义的,这就是其中之一!
  • 我要做的改进是一次性将平面列表预处理成字典,而不是在每次调用 FillChildNodes 时重新解析它
  • 您可以在第一遍中使用以键作为节点 ID 并以值作为节点的字典,并始终在第二遍中从字典中查找父节点。另外,您是否假设数据有效(没有循环,所有节点都有父节点)?
  • 是否存在递归堆栈溢出错误的固有风险?
  • @JAG:每次new 生成对象时,都有出现 OOM 错误的风险。你不会避开物体,是吗?不,因为它们很有用。与递归一样,如果您负责任地使用它。如果你真的很担心,你可以很容易地包含一个深度参数,并在超过深度时抛出一个异常......但是 SO 会做同样的事情,并且不那么随意。

标签: c# .net


【解决方案1】:

以下是将平面列表解析为字典的代码:

Dictionary<IComparable, List<Node>> nodes = new Dictionary<IComparable, List<Node>>();
Node parentNode = null;
foreach(var node in ListOfAllNodes)
{
    if(node.ParentId == null)
    {
        parentNode = node;
    }else
    {
        if(!nodes.ContainsKey(node.ParentId)){
           nodes.Add(node.ParentId, new List<Node>());
        }
        nodes[node.ParentId].Add(node);
    }
}

上面的代码假设所有节点都有一个有效的(即非空的)ParentId,除了一个节点有一个nullParentId,它将是顶部节点。然后您可以将字典用作FillChildNodes 函数的参数:

private Node FillChildNodes(Node node, Dictionary<IComparable, List<Node>> dict)
{
   foreach (var childNode in dict[node.Id].OrderBy(x => x.Name))
   {
       node.Children.Add(childNode);
       FillChildNodes(childNode);
   }
   return node;
}

// call this on the variables build above:
FillChildNodes(parentNode, nodes);

【讨论】:

  • 他的节点类本身有他想要填充的子列表。他将需要两次通行证,除非以父母优先的方式对整个列表进行排序。
  • 怎么知道 ListOfAllNodes 中的节点都有孩子?他说名单是平的..
  • 抱歉,我指的是您编辑之前的代码。我并不是说所有节点都会有孩子。我的意思是必须再次通过字典来填充子节点。
  • 节点并不都有子节点,有些是叶节点。一个节点的 parentId 为空,因此是“顶部”
  • @JAG - 我相信上面的更新代码应该可以处理它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多