用循环替换递归
我正在ASP.Net页面上工作,并且里面有一个树形视图。在树视图中,一些节点具有像分支一样的嵌套节点。我有数据在以下格式的自定义对象的列表:用循环替换递归
ID,描述,parentId的
现在,我使用的是函数递归节点添加到树视图。以下是代码片段:
private bool findParentAddNode(string id, string description, string parentid, ref List<CustomTreeNode> treeList)
{
bool isFound = false;
foreach (CustomTreeNode node in treeList)
{
if (node.id == parentid)//if current node is parent node, add in it as its child
{
node.addChild(id, description, parentid);
isFound = true;
break;
}
else if (node.listOfChildNodes != null)//have child nodes
{
isFound = findParentAddNode(id, description, parentid, ref node.listOfChildNodes);
if (isFound)
break;
}
}
return isFound;
}
上述技术运行良好,但对于多于30K的节点,其性能很慢。请建议一个算法来用循环替换这个递归调用。
因为它递归下降树,代码是做了子节点的名单线性搜索。
这意味着,对于随机分布的亲本的id,之后加入N个节点到树它将平均搜索N/2将所述第N + 1节点之前对父节点。所以节点的数量是O(N 2)。
代替线性扫描,创建ID的索引节点,并用它来快速找到父母。当您创建节点并将其添加到树中时,也将其添加到Dictionary<int,CustomTreeNode>
。如果要将节点添加到父级,请在索引中找到父级并添加它。如果addChild
返回它创建的孩子,那么代码变为:
Dictionary<int,CustomTreeNode> index = new Dictionary<int,CustomTreeNode>();
private bool findParentAddNode(string id, string description, string parentid)
{
if (!nodeIndex.TryGetValue (parentid, out parentNode))
return false;
index[id] = parentNode.addChild(id, description, parentid);
return true;
}
您需要使用findParentAddNode
之前,树的根添加到索引。
广度优先搜索的迭代版本应该是类似以下内容:
var rootNodes = new List<CustomTreeNode> { new CustomTreeNode() };
while (rootNodes.Count > 0) {
var nextRoots = new List<CustomTreeNode>();
foreach (var node in rootNodes) {
// process node here
nextRoots.AddRange(node.CustomTreeNode);
}
rootNodes = nextRoots;
}
也就是说,这不是测试,因为它是一个BFS,是不是最佳的W/R/t记忆。 (内存使用是O(n)的,不O(log n)的相比,DFS或迭代加深DFS)
它看起来更好,我会测试它。谢谢毫毛。 – 2013-02-16 13:00:18
@NadeemJamali您可能还会考虑做一个迭代DFS而不是BFS,但这在C#中有点丑陋,因为您需要修改列表而不是使用'foreach'。 (由于频繁前置,因为基于数组的'List',可能需要也可能不需要使用'LinkedList')。进一步的微观优化将初始化'nextRoots',其容量是'rootNodes.Count'的一个因子。根据您的树的分支因子的估计来调整大小。 – millimoose 2013-02-16 13:03:26
您可以从SQL Server数据库使用返回XML格式的数据的XML 然后将其绑定到treeview控件。
-1:这实际上并不是OP所做的,他正在摧毁他已有的一些树木数据。 – millimoose 2013-02-16 13:04:45
绑定数据不是问题,但实际的问题是添加节点(我以格式记录/对象)将树视图及其分支放在正确的位置。 – 2013-02-16 13:10:03
你确定递归是问题吗?除非你的树形状很奇怪,不应该是那么多层次。 – millimoose 2013-02-16 12:44:29
我相信'for loops'在30K节点上仍然会很慢。如果不使用相同参数调用函数,则递归方法很好 – ogzd 2013-02-16 12:44:52
注意:您可能会将数据源列表视为也包含三列和未排序数据的表。 – 2013-02-16 12:46:47