用循环替换递归

时间:2013-02-16 12:39:19

标签: c# algorithm loops recursion

我正在使用ASP.Net页面,其中有树视图。在树视图中,一些节点具有嵌套节点,如分支。我有以下格式的自定义对象列表中的数据:

  

Id,Description,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节点,其性能很慢。请建议使用循环替换此递归调用的算法。

3 个答案:

答案 0 :(得分:3)

当它向下递归树时,代码正在对子节点列表进行线性搜索。

这意味着对于随机分布的父ID,在向树添加N个节点之后,在添加第N + 1个节点之前,它将平均搜索父节点的N / 2个节点。因此,节点数量的成本为O(N²)。

而不是线性扫描,创建一个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之前,您需要将树的根添加到索引中。

答案 1 :(得分:-1)

广度优先搜索的迭代版本应如下所示:

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内存。 (与DFS或迭代加深DFS相比,内存使用 O(n),而不是 O(log n)

答案 2 :(得分:-1)

您可以使用 for xml 从sql server数据库返回xml格式的数据  然后将其绑定到treeview控件。