0

我有一个 TreeView,其中包含所有存储在数据库中的文件夹和文件。我现在使用 AjaxToolkit 中的自动完成搜索功能创建了一个搜索功能。一切都很好,除了我正在努力寻找具有我从搜索中获得的值的节点。我现在认为它必须是一种递归方法,但我不知道该怎么做。

所以,问题是。如何根据已有的节点值在树视图中找到节点。我还需要获取所有父节点值。所以我可以从中选择节点。

以下是部分代码(在搜索完成后的回发中):

 else
            {   
                // postBack handler for AJAX AutoComplete Extender - JavaScript call: AutoCompletedClientItemSelected
                if (Request.Form["__EVENTTARGET"] != null &&
                Request.Form["__EVENTTARGET"] == "AutoCompleteExtender" &&
                Request.Form["__EVENTARGUMENT"] != null)
                {   
                    //i have the value for the node, but i need to search for it here, 
                    //and i also need the node-values from all the parents. I need the "path"
                    string nodeValue = Session["NodeValueFromSearchForm"].ToString();
                    string nodePath = "";

                    foreach (TreeNode node in TreeViewFolders.Nodes)
                    {
                        if (node.Value == nodeValue)
                        {
                            //I'm stuck here
                            nodePath += "\\s" + node.Value;

                        }
                    }

                    string prompt = String.Format("<script>{0}{1}{2}</script>", "javascript:__doPostBack('TreeViewFolders','s", nodePath, "')");                    
                    ScriptManager.RegisterStartupScript(this, GetType(), "message", prompt, false);                    
                }
            }

foreach循环中,我只得到“根”文件夹(在顶部)。如何递归地执行此操作,以到达子节点,最后找到我拥有唯一 node.value 的节点?

感谢 Georges Oates Larsen 的回答,我得到了它的工作。当用户在树视图中上传文件时,我没有考虑只保存节点的值路径。所以,现在我在上传过程中将值路径保存在我的“文件”表中,并将该值传递给__doPostBack

4

1 回答 1

1

我不完全确定您的 TreeView 对象的工作方式有多精确,或者您如何存储它的数据(或者它是否存储自己的数据)。但是,我确实对树搜索算法有所了解。

查找所需内容的最快方法主要取决于您的树是否已排序。我将假设它没有排序,这意味着解决方案将有 O(N) 的最坏情况,N 是树中的节点数。

还有不同类型的树——我将假设您使用的是普通的老树(任意数量的子树,不超过一个父节点,一个根节点)。如果您提供有关您正在使用的树的更多信息,我们可以提供有关如何最好地遍历它的更好信息。

鉴于这些假设,伪代码如下:

public TreeNode[] SearchTree(Tree YourTree, SearchObject SearchingFor)
{
    return SearchNode(0, YourTree.RootNode, SearchingFor);//Depth is sent in so that our recursion can keep track of how many parents the node has. This allows us to use simple arrays which are far faster than any alternative serial data storage.
}

public TreeNode[] SearchNode(int depth, TreeNode YourNode, SearchObject SearchingFor)
{
    //Edge case


    if (SearchingFor.Matches(YourNode))//Does the node match our search?
    {
        return GetHeritage(depth, YourNode);//We get the heritage at the end because it's faster than using a dynamically allocated array for every single recursion we do when only one will ever get used. That practically makes the memory used exponential! Not ot mention all of the slowdown caused by the algorithms required for reallocation.
    }


    //Recurse

    TreeNode[] ret = null;
    for (int i = 0; i < YourNode.ChildNodes.Length; i++)
    {
        //Set the ret temporary variable to our recursion, then see if it is null or not
        if ((ret = SearchNode(depth+1, YourNode.ChildNodes[i])) != null)
        {
            break;//Exit the loop!
        }
    }


    //Return the result

    return ret;//If we find the correct answer, the loop will break with ret at the correct value.
    //If, however, we do not find anything correct within this node, we will simply return null.
}



//Final calculation for the correct result.

public TreeNode[] GetHeritage(int depth, TreeNode YourNode)//This will list every node starting from the node we found going all the way back to the root node. The first element in the array returned will be the root node.
{
    TreeNode[] ret = new TreeNode[depth+1];
    ret[depth] = YourNode;//Depth is actually one less than our length, so... Hurrah!
    for (int i = depth; i >= 0; i--)
    {
        ret[depth-i] = ret[depth-(i-1)].Parent;
    }

    return ret;
}

编辑:我已经阅读了您的一些评论:

一种更快的方法是简单地创建一个数组并使用“自动递增 ID”的索引添加对每个节点的引用,每次向 TreeView 添加内容时,该索引都指向相应的节点。然后要获取您的号码的路径,只需查看辅助数组中 index[number] 处的节点,然后跟随其父节点直到根节点!:)

于 2012-07-20T19:03:46.400 回答